In the console in the image below, you can see that automatic linking probably isn't working correctly. What do I need to do? Below is the code I'm using. I also did a refresh, clean, and rebuild, but the error remains.
/*
* Fibonacci.h
*
* Created on: Apr 2, 2014
* Author: rose
*/
#ifndef FIBONACCI_H_
#define FIBONACCI_H_
unsigned int Fibonacci(unsigned int n);
#endif /* FIBONACCI_H_ */
/*
* Fibonacci.cpp
*
* Created on: Apr 2, 2014
* Author: rose
*/
#include "Fibonacci.h"
unsigned int Fibonacci(unsigned int n)
{
if (n==1) {
return 1;
} else if (n == 0) {
return 0;
}
return Fibonacci(n-2) + Fibonacci(n-1);
}
/*
* main.cpp
*
* Created on: Apr 2, 2014
* Author: rose
*/
#include <iostream>
#include "Fibonacci.h"
int main(int argc, char *argv[])
{
std::cout << "Fibonacci(10) = " << Fibonacci(10) << std::endl;
}
It's not a linker problem, its the compiler. You need to include Fibonacci.h in main.cpp.
Related
I've been attempting to solve the longest common subsequence problem using multiprocessing and multi-threading, and I have implemented a multiprocess version of the code, using the usual dynamic programming approach: generate a score matrix, each element depends on the one to its left, north-west and directly above.
In my multiprocess approach, I have adopted propagating the wavefront along the anti-diagonals of the score matrix, and to make life easy, I have performed a shear transform on said score matrix, so that each antidiagonal is now horizontal (this is for improved memory access):
Following is my code (admittedly rather long, which allows for some set-up):
#include <algorithm>
#include <atomic>
#include <cstring>
#include <fcntl.h>
#include <fstream>
#include <iostream>
#include <string>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include <x86intrin.h>
#define LOGICAL_CORES (int) sysconf(_SC_NPROCESSORS_CONF) /* Number of
logical cores on system: indirectly determines number of processes run */
#define MAX_WORK_SIZE 256 /* Maximum amount
of work for each worker process */
#define NUM_ANTIDIAGS (X + Y + 1) /* Number of anti-
diagonals to process */
#define ANTIDIAG_SIZE std::max(X, Y) /* Length of each
anti-diagonal of the score matrix */
#define ANTIDIAG_REAL_SIZE ((ANTIDIAG_SIZE + MAX_WORK_SIZE - 1) & -MAX_WORK_SIZE) /* Length of each
anti-diagonal in memory: a multiple of MAX_WORKER_SIZE */
#define NUM_WORKERS (ANTIDIAG_REAL_SIZE / MAX_WORK_SIZE) /* Total number of
worker processes */
// The sizes of the input strings
u_int32_t X, Y;
u_int32_t *back; /* The back anti-diagonal, read from */
u_int32_t *middle; /* The middle antidiagonal, read from */
u_int32_t *front; /* The front antidiagonal, written to */
struct sync_container {
pthread_barrier_t barrier; /* A barrier, to ensure all threads are synchronised */
pthread_barrierattr_t barrierattr; /* Barrier attributes */
std::vector<pid_t> pids; /* A list of process IDs of the worker processes */
};
u_int32_t *data;
sync_container *sync_data;
std::string seq_1;
std::string seq_2;
void read_files(std::ifstream f1, std::ifstream f2)
{
if (f1.fail() || f2.fail())
{
std::cout << "Error reading files; exiting." << std::endl;
exit(EXIT_FAILURE);
}
f1 >> X >> seq_1;
f1.close();
f2 >> Y >> seq_2;
f2.close();
}
void shm_setup()
{
data = reinterpret_cast<u_int32_t *>(mmap(nullptr, 4 * ANTIDIAG_REAL_SIZE * sizeof(uint32_t),
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, 0, 0));
back = reinterpret_cast<u_int32_t *>(data);
middle = back + ANTIDIAG_REAL_SIZE;
front = middle + ANTIDIAG_REAL_SIZE;
memset(back, 0, ANTIDIAG_REAL_SIZE * sizeof(u_int32_t));
memset(middle, 0, ANTIDIAG_REAL_SIZE * sizeof(u_int32_t));
memset(front, 0, ANTIDIAG_REAL_SIZE * sizeof(u_int32_t));
sync_data = static_cast<sync_container *>(mmap(nullptr, sizeof(sync_container),
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, 0, 0));
}
void cleanup()
{
munmap(data, 3 * ANTIDIAG_REAL_SIZE * sizeof(u_int32_t));
munmap(sync_data, sizeof(sync_container));
exit(0);
}
int main(int argc, char **argv)
{
if (argc != 3)
{
std::cout << "Usage: [executable] [file 1] [file 2]" << std::endl;
return 1;
}
read_files(std::ifstream(argv[1], std::ifstream::in),
std::ifstream(argv[2], std::ifstream::in));
// Initialise shared memory and arrays
shm_setup();
// Initialise barrier
pthread_barrierattr_init(&sync_data->barrierattr);
pthread_barrierattr_setpshared(&sync_data->barrierattr, PTHREAD_PROCESS_SHARED);
pthread_barrier_init(&sync_data->barrier, &sync_data->barrierattr, NUM_WORKERS + 1);
int pid = 0;
int worker_id = 0;
for (; worker_id < NUM_WORKERS; ++worker_id)
{
pid = fork();
if (pid) sync_data->pids[worker_id] = pid;
else
break;
}
pthread_barrier_wait(&sync_data->barrier);
for (int antidiag_idx = 2; antidiag_idx < NUM_ANTIDIAGS; ++antidiag_idx)
{
pthread_barrier_wait(&sync_data->barrier);
if (!pid) // worker processes go here
{
for (int element = MAX_WORK_SIZE * worker_id; element < (antidiag_idx * worker_id) + MAX_WORK_SIZE; ++element)
{
if (!element || element >= ANTIDIAG_SIZE) continue;
char vert = seq_1[antidiag_idx - 1 - element];
char horz = seq_2[element - 1];
front[element] = horz == vert ? back[element - 1] + 1
: std::max(middle[element - 1], middle[element]);
}
}
if (pid) // parent process moves pointers
{
back = middle;
middle = front;
front = back;
}
pthread_barrier_wait(&sync_data->barrier);
}
if (!pid) exit(0);
std::cout << middle[ANTIDIAG_SIZE] << std::endl;
cleanup();
}
Now, this code does not work. This is strange, because with a small input size (specifically, < 256), this code only spawns one worker process and one parent process to manage it, and it still fails.
However, when the fork(), various pthread_barrier_wait() calls, and if (pid) control flow paths are removed in the for loop, the code executes perfectly and returns the correct expected length of the LCS between two strings specified in the input files. In other words, it degenerates into effectively a single-threaded, single-process version of the dynamic programming solution, but with the shear transform thing.
There is clearly an issue with my synchronisation, and I can't figure out where it is. I've tried several permutations of adding more pthread_barrier_wait()s, but this hasn't led anywhere.
Where is the synch issue, and how may I fix it?
I am having a very weird error while trying to create a CUDA kernel to execute a for loop:
#include <stdlib.h>
#include <stdio.h>
#include <thrust/reduce.h>
#include <cuda.h>
int main(int argc, char** argv)
{
float *arrayA;
cudaMalloc((void**)&arrayA, 4096 * 4096 * sizeof(float));
float *arrayB;
cudaMalloc((void**)&arrayB, 4096 * 4096 * sizeof(float));
__global__ void loopKernel(float* arrayA, float* arrayB)
{
int i = threadIdx.x + blockDim.x*blockIdx.x;
if (i < m)
{
//do stuf
}
}
loopKernel << 8, 256 >> (arrayA, arrayB);
}
the error is on the opening { for the kernel (line 14):
error: expected a ";"
it seems really odd as I get the same error on Visual Studio and linux terminal, so it is not an OS issue.
The file is also .cu so there is no way it's being sent to the wrong compiler.
Any help will be appreciated.
A __global__ function definition (i.e. kernel definition) is not something you do within the body of another function. We don't typically do this in C or C++ either (a C/C++ function definition is not usually placed within the body of another function definition).
Place your kernel definitions at global scope (i.e. outside the body of any other function definition, including main).
Something like this:
#include <stdlib.h>
#include <stdio.h>
#include <thrust/reduce.h>
#include <cuda.h>
__global__ void loopKernel(float* arrayA, float* arrayB)
{
int i = threadIdx.x + blockDim.x*blockIdx.x;
if (i < m)
{
arrayA[i] = 0.f;
arrayB[(n - 1)*m + i] = 0.f;
}
}
int main(int argc, char** argv)
{
float *arrayA;
cudaMalloc((void**)&arrayA, 4096 * 4096 * sizeof(float));
float *arrayB;
cudaMalloc((void**)&arrayB, 4096 * 4096 * sizeof(float));
loopKernel << 8, 256 >> (arrayA, arrayB);
}
There are various other issues with the posted code:
It provided no definition for m or n.
The kernel calling syntax is wrong, instead of <<...>> it should be <<<...>>>
For these types of basic issues, its probably better to study a simple (correct) code like the vectorAdd sample code.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I am programming a c/c++ SDL synth which works on linux, windows, and handled psp and I mix c/c++ in multiple part of the code.
I use new/malloc and I don't think I mix them up but if I do please tell me where and why.
My main program is now near 20 000 line and it works fine.
But I allways fall into a bug when I began to modify it and I can not understand and spot my real error.
I fall into SIGSEV when I began to modify some part of my code and it take me hours to make it work without understand why I fall into this.
And after some modification it works again, and I have no clue about why I have a SIGSEV and why it is fixed now and how I can have modify it to make it works and prevent future mistake.
So I ask you to explain it what is my real error.
Here is a gdb log with a really strip down version and the kind of crash I have :
yoyz#yoyz-laptop:~/build/audio/picoloop/tmp/ gdb ./WaveTable
GNU gdb (GDB) 7.4.1-debian
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/yoyz/build/audio/picoloop/tmp/WaveTable...done.
(gdb) r
Starting program: /home/yoyz/build/audio/picoloop/tmp/WaveTable
warning: the debug information found in "/lib64/ld-2.13.so" does not match "/lib64/ld-linux-x86-64.so.2" (CRC mismatch).
Generator::init() Allocating memory
Generator::one() 0x00604010
Generator::sine() 0x00604010
Generator::saw() 0x00604010
Generator::pulse() 0x00604010
Program received signal SIGSEGV, Segmentation fault.
_int_malloc (av=0x7ffff7639e40, bytes=32768) at malloc.c:4738
4738 malloc.c: No such file or directory.
(gdb)
Here is the strip down version of the code :
#include "MyMaster.h"
#include "Generator.h"
#include "WaveTable.h"
#include "WaveTableManager.h"
int main(int argc,char **argv)
{
Generator G;
WaveTableManager & WTM = WaveTableManager::getInstance();
WaveTable* WT;
G.init();
WT = new WaveTable();
WT->setSize(WAVETABLE_SIZE);
G.one();
memcpy(WT->getBuffer(),G.getBuffer(),WAVETABLE_SIZE*DEFAULTBITRATE/8);
WTM.insert(WT,PICO_WAVETABLE_ONE);
WT = new WaveTable();
WT->setSize(WAVETABLE_SIZE);
G.sine();
memcpy(WT->getBuffer(),G.getBuffer(),WAVETABLE_SIZE*DEFAULTBITRATE/8);
WTM.insert(WT,PICO_WAVETABLE_SINE);
WT = new WaveTable();
WT->setSize(WAVETABLE_SIZE);
G.saw();
memcpy(WT->getBuffer(),G.getBuffer(),WAVETABLE_SIZE*DEFAULTBITRATE/8);
WTM.insert(WT,PICO_WAVETABLE_SAW);
WT = new WaveTable();
WT->setSize(WAVETABLE_SIZE);
G.pulse();
memcpy(WT->getBuffer(),G.getBuffer(),WAVETABLE_SIZE*DEFAULTBITRATE/8);
WTM.insert(WT,PICO_WAVETABLE_PULSE);
WT = new WaveTable();
WT->setSize(WAVETABLE_SIZE);
G.triangle();
memcpy(WT->getBuffer(),G.getBuffer(),WAVETABLE_SIZE*DEFAULTBITRATE/8);
WTM.insert(WT,PICO_WAVETABLE_TRGL);
WT = new WaveTable();
WT->setSize(WAVETABLE_SIZE);
G.noise();
memcpy(WT->getBuffer(),G.getBuffer(),WAVETABLE_SIZE*DEFAULTBITRATE/8);
WTM.insert(WT,PICO_WAVETABLE_NOISE);
printf("wavetablemanager.getSize : %d\n",WTM.getSize());
}
MyMaster.h
#ifndef __MASTER____
#define __MASTER____
#include <SDL/SDL.h>
#define WAVETABLE_SIZE 1024*16
#define DEFAULTBITRATE 16
enum
{
PICO_WAVETABLE_SINE,
PICO_WAVETABLE_SAW,
PICO_WAVETABLE_PULSE,
PICO_WAVETABLE_TRGL,
PICO_WAVETABLE_NOISE,
PICO_WAVETABLE_ONE,
PICO_WAVETABLE_SIZE
};
#endif
Generator.h
using namespace std;
#include <SDL/SDL_types.h>
#include <math.h>
#include "MyMaster.h"
#ifndef __GENERATOR__
#define __GENERATOR__
class Generator
{
public:
Generator();
~Generator();
void init();
void sine();
void saw();
void pulse();
void triangle();
void noise();
void one();
Sint16 * getBuffer();
private:
Sint16 * table;
int table_size;
int index;
int d;
};
#endif
Generator.cpp
#include "Generator.h"
Generator::Generator()
{
table_size=WAVETABLE_SIZE;
}
Generator::~Generator()
{
}
void Generator::init()
{
if (table_size>0)
{
printf("Generator::init() Allocating memory\n");
table=(Sint16*)malloc(sizeof(Sint16)*table_size);
if (table==0)
{
printf("Error allocating memory\n");
//return 0;
}
}
}
void Generator::sine()
{
int i;
float f;
Sint16 s;
Sint16 bitdepth=16-1;
printf("Generator::sine() 0x%08.8X\n",table);
for (i=0;i<table_size;i++)
{
s=sin((2*3.14159*i*1)/table_size)*(1<<bitdepth-2);
table[i]=s;
//printf("table[%d]=%d\n",i,s);
}
}
void Generator::saw()
{
int i;
float f;
Sint16 s;
Sint16 bitdepth=16;
Sint16 dec;
printf("Generator::saw() 0x%08.8X\n",table);
s=(1<<(bitdepth-2));
dec=(1<<(bitdepth-2))/(table_size/2);
for (i=0;i<table_size;i++)
{
table[i]=s;
s=s-dec;
}
}
void Generator::pulse()
{
int i;
float f;
Sint16 s;
Sint16 bitdepth=16;
Sint16 dec=(1<<(bitdepth-2))/(table_size/2);
printf("Generator::pulse() 0x%08.8X\n",table);
for (i=0;i<table_size/2;i++)
{
table[i]=((1<<(bitdepth-2))/2);
}
for (i=table_size/2;i<table_size;i++)
{
table[i]=((1<<(bitdepth-2))*-1)/2;
}
}
void Generator::triangle()
{
int i;
float f;
Sint16 s=0;
Sint16 bitdepth=16;
Sint16 dec=(1<<(bitdepth-2))/(table_size/4);
printf("Generator::triangle() 0x%08.8X\n",table);
//table=(Sint16*)malloc(sizeof(Sint16)*table_size);
for (i=0;i<(table_size*1)/4;i++)
{
table[i]=s;
s=s+dec;
}
for (i=(table_size*1)/4;i<(table_size*3)/4;i++)
{
table[i]=s;
s=s-dec;
}
for (i=(table_size*3)/4;i<table_size;i++)
{
table[i]=s;
s=s+dec;
}
}
void Generator::noise()
{
int i;
float f;
Sint16 s;
Sint16 bitdepth=16;
printf("Generator::noise() 0x%08.8X\n",table);
srand(1<<(bitdepth-2));
for (i=0;i<table_size;i++)
{
if (rand()%2==0)
table[i]=rand()%8192;
else
table[i]=(rand()%8192)*-1;
}
}
void Generator::one()
{
int i;
float f;
Sint16 s;
Sint16 bitdepth=16;
printf("Generator::one() 0x%08.8X\n",table);
for (i=0;i<table_size;i++)
{
table[i]=1<<bitdepth-1;
}
}
Sint16 * Generator::getBuffer()
{
return table;
}
WaveTable.h
#include "MyMaster.h"
#include <SDL/SDL_types.h>
#ifndef __WAVETABLE__
#define __WAVETABLE__
class WaveTable
{
public:
WaveTable();
~WaveTable();
int setSize(int bufferSize);
int allocMemory();
int freeMemory();
Sint16 * getBuffer();
char * getName();
Sint32 getSize();
private:
Sint32 size;
Sint16 * buffer;
char * name;
};
#endif
WaveTable.cpp
#include "WaveTable.h"
using namespace std;
WaveTable::WaveTable()
{
size=0;
buffer=0;
name=0;
}
WaveTable::~WaveTable()
{
}
int WaveTable::allocMemory()
{
if (size>0)
{
buffer=(Sint16*)malloc(sizeof(Sint16)*size);
if (buffer==0)
{
printf("Error allocating memory\n");
return 0;
}
}
return size;
}
int WaveTable::freeMemory()
{
if (buffer!=0)
{
free(buffer);
buffer=0;
}
}
int WaveTable::setSize(int bufferSize)
{
if (bufferSize>=0)
size=bufferSize;
if (buffer!=0)
this->freeMemory();
return this->allocMemory();
}
Sint16 * WaveTable::getBuffer()
{
return buffer;
}
WaveTableManager.h
using namespace std;
#include <vector>
#include "WaveTable.h"
#ifndef __WAVETABLEMANAGER__
#define __WAVETABLEMANAGER__
class WaveTableManager
{
private:
WaveTableManager();
~WaveTableManager();
vector<WaveTable*> wtvector;
int size;
public:
static WaveTableManager& getInstance();
int getSize();
void insert(WaveTable * WT,int position);
WaveTable * get(int position);
};
#endif
WaveTableManager.cpp
#include "WaveTableManager.h"
WaveTableManager::WaveTableManager() : wtvector()
{
size=0;
}
WaveTableManager::~WaveTableManager()
{
}
WaveTableManager& WaveTableManager::getInstance()
{
static WaveTableManager instance;
return instance;
}
int WaveTableManager::getSize()
{
return wtvector.size();
}
void WaveTableManager::insert(WaveTable * WT,int position)
{
if (wtvector.size()<=position)
wtvector.resize(position);
wtvector[position]=WT;
}
WaveTable * WaveTableManager::get(int position)
{
return wtvector[position];
}
Makefile.WaveTable
CC=g++
CFLAGS=-O0 -DLINUX -D__RTAUDIO__ -DLINUX_DESKTOP -I. -LSDL/lib -g -fpermissive
SOURCES=WaveTableTest.cpp WaveTable.cpp WaveTableManager.cpp Generator.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=WaveTable
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $#
.cpp.o:
$(CC) -c $(CFLAGS) $< -o $#
clean:
-rm -f $(OBJECTS) $(EXECUTABLE)
Here is one issue:
void WaveTableManager::insert(WaveTable * WT,int position)
{
if (wtvector.size()<=position)
wtvector.resize(position);
wtvector[position]=WT; // < -- Out of bounds access
}
When you call resize(), the upper bound is vector::size()-1. Since position is the new size of the vector, what you probably want is this:
wtvector[position - 1] = WT;
The system is: Linux/CentOS 6.4
I keep getting an error for functions not declared in scope. Is it not legal to call a function within another function? I read an article on function, thought it was because I needed to declare the functions void when I call them, but I received new errors. I am not sure if I need to declare them global or something.
client.cpp:32: error: 'takef' was not declared in this scope
client.cpp:33: error: 'putf' was not declared in this scope
client.cpp: In function 'void takef(int&)':
client.cpp:44: error: 'testa' was not declared in this scope
client.cpp: In function 'void putf(int&)':
client.cpp:70: error: 'test' was not declared in this scope
Example of the type of code I'm trying to implement:
sem_t mutex;
sem_t S;
char buffer[1024];
void error(const char *msg)
{
perror(msg);
exit(0);
}
/*
void signal_callback_handler()
{
close(sockfd);
}
*/
void father(int &sockfd)
{
while(1)
{
srand(time(NULL));
int ms = rand() % 2000 + 5000
send(sockfd, DATA, strlen(DATA), 0);
usleep(1000*ms);
takef(sockfd);
putf(sockfd);
}
}
void takef(int &sockfd)
{
/*
*
* *Other code*
*
*
*/
testa(sockfd);
/* *Other code*
*
*
*/
}
void testa(int &sockfd)
{
/*
*
*
* *Other code*
*
*
*/
}
void putf(&sockfd)
{
/*
*
*
* *Other code*
*
*
*/
test();
test();
sem_post(&mutex);
}
int main(int argc, char *argv[])
{
/*
*
*
* *Other code*
*
*
*/
father(sockfd);
return 0;
}
In C++ you need to declare the functions before they are used.
Include the prototype of the functions before you start defining any of the functions.
Simple fix. Move the function definitions above the void father() function.
In code
sem_t mutex;
sem_t S;
char buffer[1024];
void error(const char *msg)
{
perror(msg);
exit(0);
}
/*
void signal_callback_handler()
{
close(sockfd);
}
*/
void takef(int &sockfd)
{
/*
*
* *Other code*
*
*
*/
testa(sockfd);
/* *Other code*
*
*
*/
}
void testa(int &sockfd)
{
/*
*
*
* *Other code*
*
*
*/
}
void putf(&sockfd)
{
/*
*
*
* *Other code*
*
*
*/
test();
test();
sem_post(&mutex);
}
void father(int &sockfd)
{
while(1)
{
srand(time(NULL));
int ms = rand() % 2000 + 5000
send(sockfd, DATA, strlen(DATA), 0);
usleep(1000*ms);
takef(sockfd);
putf(sockfd);
}
}
int main(int argc, char *argv[])
{
/*
*
*
* *Other code*
*
*
*/
father(sockfd);
return 0;
}
Or another alternative, like mentioned below, is to write a function prototype. This is similar to how one would write a prototype for functions in a header file and then define the functions in a .cpp file. A function prototype is a function without a body and lets the compiler know the function exists but is not defined yet.
Here is an example using prototyping
sem_t mutex;
sem_t S;
char buffer[1024];
void error(const char *msg)
{
perror(msg);
exit(0);
}
/*
void signal_callback_handler()
{
close(sockfd);
}
*/
// Prototypes
void takef(int &sockfd);
void testa(int &sockfd);
void putf(&sockfd);
void father(int &sockfd)
{
while(1)
{
srand(time(NULL));
int ms = rand() % 2000 + 5000
send(sockfd, DATA, strlen(DATA), 0);
usleep(1000*ms);
takef(sockfd);
putf(sockfd);
}
}
void takef(int &sockfd)
{
/*
*
* *Other code*
*
*
*/
testa(sockfd);
/* *Other code*
*
*
*/
}
void testa(int &sockfd)
{
/*
*
*
* *Other code*
*
*
*/
}
void putf(&sockfd)
{
/*
*
*
* *Other code*
*
*
*/
test();
test();
sem_post(&mutex);
}
int main(int argc, char *argv[])
{
/*
*
*
* *Other code*
*
*
*/
father(sockfd);
return 0;
}
I get this error when trying to compile my program:
Field '__jmpbuf' could not be resolved
I looked for a solution for hours and can't seem to find out where is the culprit.
The Thread.h file contains the header of the class. It has the private member:
sigjmp_buf _env;
And the implementation is inside Thread.cpp:
#include "Thread.h"
#include <setjmp.h>
#include "translateAdd.h"
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <sys/time.h>
#define COUNTER_INIT -1
int Thread::_idCounter = COUNTER_INIT;
Thread::Thread(void (*threadsFunc)(void))
: threadsFunction(threadsFunc), _stack(new char[STACK_SIZE]), _quantums(1)
{
address_t sp, pc;
sp = (address_t)_stack + STACK_SIZE - sizeof(address_t);
pc = (address_t)threadsFunc;
// set environment for later return
sigsetjmp(_env, 1);
(_env->__jmpbuf)[JB_SP] = translate_address(sp);
(_env->__jmpbuf)[JB_PC] = translate_address(pc);
sigemptyset(&_env->__saved_mask);
_id = ++_idCounter;
_state = READY;
}
EDIT: Using eclipse as the IDE under ubuntu 32bit
EDIT: Another complete example that doesn't compile on my machine:
#include <stdio.h>
#include <setjmp.h>
#include <signal.h>
#include <unistd.h>
#include <sys/time.h>
#define SECOND 1000000
#define STACK_SIZE 4096
char stack1[STACK_SIZE];
char stack2[STACK_SIZE];
sigjmp_buf env[2];
#ifdef __x86_64__
/* code for 64 bit Intel arch */
typedef unsigned long address_t;
#define JB_SP 6
#define JB_PC 7
/* A translation is required when using an address of a variable.
Use this as a black box in your code. */
address_t translate_address(address_t addr)
{
address_t ret;
asm volatile("xor %%fs:0x30,%0\n"
"rol $0x11,%0\n"
: "=g" (ret)
: "0" (addr));
return ret;
}
#else
/* code for 32 bit Intel arch */
typedef unsigned int address_t;
#define JB_SP 4
#define JB_PC 5
/* A translation is required when using an address of a variable.
Use this as a black box in your code. */
address_t translate_address(address_t addr)
{
address_t ret;
asm volatile("xor %%gs:0x18,%0\n"
"rol $0x9,%0\n"
: "=g" (ret)
: "0" (addr));
return ret;
}
#endif
void switchThreads(void)
{
static int currentThread = 0;
int ret_val = sigsetjmp(env[currentThread],1);
printf("SWITCH: ret_val=%d\n", ret_val);
if (ret_val == 1) {
return;
}
currentThread = 1 - currentThread;
siglongjmp(env[currentThread],1);
}
void f(void)
{
int i = 0;
while(1){
++i;
printf("in f (%d)\n",i);
if (i % 3 == 0) {
printf("f: switching\n");
switchThreads();
}
usleep(SECOND);
}
}
void g(void)
{
int i = 0;
while(1){
++i;
printf("in g (%d)\n",i);
if (i % 5 == 0) {
printf("g: switching\n");
switchThreads();
}
usleep(SECOND);
}
}
void setup(void)
{
address_t sp, pc;
sp = (address_t)stack1 + STACK_SIZE - sizeof(address_t);
pc = (address_t)f;
sigsetjmp(env[0], 1);
(env[0]->__jmpbuf)[JB_SP] = translate_address(sp);
(env[0]->__jmpbuf)[JB_PC] = translate_address(pc);
sigemptyset(&env[0]->__saved_mask);
sp = (address_t)stack2 + STACK_SIZE - sizeof(address_t);
pc = (address_t)g;
sigsetjmp(env[1], 1);
(env[1]->__jmpbuf)[JB_SP] = translate_address(sp);
(env[1]->__jmpbuf)[JB_PC] = translate_address(pc);
sigemptyset(&env[1]->__saved_mask);
}
int main(void)
{
setup();
siglongjmp(env[0], 1);
return 0;
}
If you really need to use the internal fields (which will only be valid for your compiler on your system) you need to check the types:
typedef struct __jmp_buf_tag sigjmp_buf[1];
That means that sigjmp_buf is not a pointer, but an array with a single structure in it. So you use it like a normal array of structures:
sigjmp_buf _env;
_env[0].__jmpbuf[x] = y;
I really recommend against the use the internal field of this structure. Linux have other functions to simplify cooperative threading (which is what you seem to be implementing).