I'm actually writing an MPI program. This is a basic client / server pattern. The server have a set of work to compute. The clients get subsets of this big set. Each client use several threads to compute the subset. I must be sure all the threads finished before requesting another subset to the server.
The client is split into several threads: a master (for the communications) and several workers.
Here my actual code, where the deadlock should occur. I cleaned it of any MPI calls, to make it more readable. I really can not see what I am doing wrong here.
void* worker ( void * arg ) {
while (work != 0) {
int x;
while ( get_job(&x) ) {
do_job(x);
}
pthread_mutex_lock(&mutex_worker);
nb_job_empty++;
if (nb_job_empty == NB_THREADS) {
nb_job_empty = 0;
pthread_cond_signal(&cond_master);
}
nb_worker_woken--;
pthread_cond_wait(&cond_worker, &mutex_worker);
nb_worker_woken++;
pthread_mutex_unlock(&mutex_worker);
}
return ( void * ) 0 ;
}
void server() {
for (int i = 0; i < 100; i++) {
add_job();
pthread_mutex_lock(&mutex_master);
pthread_cond_broadcast(&cond_worker);
pthread_cond_wait(&cond_master, &mutex_master);
pthread_mutex_unlock(&mutex_master);
}
work = 0;
pthread_mutex_lock(&mutex_master);
pthread_cond_broadcast(&cond_worker);
pthread_mutex_unlock(&mutex_master);
}
You should use the same mutex for both condition (mutex_master and mutex_worker should be the same)
Moreover, you should use pthread_cond_wait in a while loop as it is recommended :)
Related
I am measuring wall time through the use of clock_gettime() found in . It works perfectly fine when i use it in main() but not the way i am attempting to use it.
I am familiarizing myself with the linux scheduler and i am measuring performance on different parts.
I want to be able to measure Waiting time which is defined by "the total time a thread spends in the ready queue" (how long until it starts executing the function).
Easily enough i can measure this by setting a clock_gettime() before the thread function and another right inside the function. However the problem i am having is that the time inside the thread function is lower than the one outside, giving us a negative time.
I am running this on my windows pc through ubuntu.
what could the problem be?
code:
clock_gettime(CLOCK_REALTIME,&data.before);
thread_array[i-1] = data;
if(pthread_create(&tids[i],&attr,workLoad,(void*) &data) != 0){
perror("Could not create thread");
return 1;
}
}
for(int i = 1;i < threadAmount; i++){
if(pthread_join(tids[i],NULL)!= 0){
perror("Thread could not wait");
return 1;
}
}
and here is my threadfunc:
void *workLoad(void *args)
{
threadData* data = (threadData*) args;
clock_gettime(CLOCK_REALTIME,&data->after);
int loopAmount = data->loopAmount;
int counter = 0;
for(int i = 0; i < loopAmount; i++){
counter++;
}
return NULL;
}
result of time intervall
In the following code:
clock_gettime(CLOCK_REALTIME,&data.before);
thread_array[i-1] = data;
if(pthread_create(&tids[i],&attr,workLoad,(void*) &data) != 0){
data seems to be a local variable whose address you pass to the thread. You also copy this variable into thread_array[i-1]. If you then do thread_array[i-1].after - thread_array[i-1].before then that means that the thread updates a wrong variable. You need to pass &thread_array[i-1] to that thread, e.g.:
if(pthread_create(&tids[i],&attr,workLoad,(void*)&thread_array[i-1]) != 0){
The title might not appear particularly clear, but the code explains itself:
int shared_variable;
int get_shared_variable() {
int result;
pthread_mutex_lock(&shared_variable_mutex);
result = shared_variable;
pthread_mutex_unlock(&shared_variable_mutex);
return result;
}
void* thread_routine(void *arg) {
while (get_shared_variable() < 5000) {
printf();
printf();
sleep(2);
int i = 0;
while (pthread_mutex_trylock(&foo_mutexes[i]) != 0) {
i++;
pthread_mutex_lock(&foo_count_mutex);
if (i == foo_count) {
pthread_mutex_unlock(&foo_count_mutex);
sleep(1); // wait one second and retry
i = 0;
}
pthread_mutex_unlock(&foo_count_mutex);
}
pthread_mutex_lock(&shared_variable_mutex);
shared_variable += 10;
pthread_mutex_unlock(&shared_variable_mutex);
}
return NULL;
}
I'm passing thread_routine to a pthread_create (pretty standard), but I'm having a problem with the synchronization of the result. Basically, the problem is that the first thread checks the while condition, it passes, and then another thread checks it, it passes too. However, when the first thread finishes and shared_variable reaches 5000, the second thread has not yet finished and it adds up another 10 and the end result becomes 5010 (or NUM_OF_THREADS - 1 * 10 if I run more than two) at the end, while the whole process should end at 5000.
Another issue is that in // do some work I output something on the screen, so the whole thing inside the loop should pretty much work as a transaction in database terms. I can't seem to figure out how to solve this problem, but I suppose there's something simple that I'm missing. Thanks in advance.
This answer may or may not be what you are after. Because as explained in the comments your description of the expected behaviour of the program is incomplete. Without the exact expected behaviour it is difficult to give a full answer. But since you ask, here is a possible structure of the program based on the code shown. The main principle it is illustrating is that the critical section for shared_variable needs to be both minimal and complete.
int shared_variable;
void* thread_routine(void *arg)
{
while (1) {
pthread_mutex_lock(&shared_variable_mutex);
if (shared_variable >= 5000) {
pthread_mutex_unlock(&shared_variable_mutex);
break;
}
shared_variable += 10;
pthread_mutex_unlock(&shared_variable_mutex);
/* Other code that doesn't use shared_variable goes here */
}
return NULL;
}
I am trying to implement a mutex in c using the fetch and increment algorithm (sort of like the bakery algorithm). I have implemented the fetch and add part atomically. I have every thread obtain a ticket number and wait for their number to be "displayed". However, I have not found a way to tackle the issue of waiting for your ticket to be displayed. I have thought of using a queue to store your thread ID and descheudle/yield yourself until someone who has the lock, wakes you up. However, I would need a lock for the queue as well! :(
Are there any recommendations on what I could do to make the queue insertion safe or perhaps a different approach to using a queue?
Here is some code of my initial implementation:
void mutex_lock( mutex_t *mp ) {
while (compareAndSwap(&(mp->guard), 0, 1) == 1) {
// This will loop for a short period of time, Need to change this <--
}
if ( mp->lock == 1 ) {
queue_elem_t elem;
elem.data.tid = gettid();
enq( &(mp->queue), &(elem) );
mp->guard = 0;
deschedule();
}
else {
mp->lock = 1; // Lock the mutex
mp->guard = 0; // Allow others to enq themselves
}
}
Also, lets for now ignore the potential race condition where someone can call make_runnable before you call deschedule, I can write another system call that will say we are about to deschedule so queue make_runnable calls.
I'm testing an idea for detailed error handling, and want to enable a thread to have the ability to call a 'getlasterror' function when it needs to work with the error. I'm using a cheap and simple pointer-to-pointers for the structs, but also make use of the pthread_t id to overwrite a previous entry (if the error info was not needed or has been processed).
From the stackoverflow posts How do you query a pthread to see if it is still running? and How do I determine if a pthread is alive?, it seems using pthread_kill to send a fake signal is potentially unsafe. Is there really no alternative mechanism to check if a pthread with an id exists or not? Or can I disable the ability for thread ids to be reused at runtime? (I'm aware the latter may be a security issue...)
I'd not previously written any code, but I whipped up roughly what my plan would look like below in leafpad (so ignore any syntax errors, if any!). Point of interest is naturally the dynamic cleanup, there's no problem if the application is closing. Any other alternative ideas would also be welcome :)
If applicable, this will be a client/server program, hence a new thread will exist with each accept().
struct error_info_structs
{
struct error_info** errs; // error_info struct with details
pthread_t** tids; // thread ids for each struct
uint32_t num; // number of error_info structs and thread ids
pthread_mutex_lock lock; // runtime locker
};
struct error_info_structs g_errs;
// assume we've done necessary initialization...
struct error_info*
get_last_runtime_error()
{
struct error_info* retval = NULL;
pthread_t tid = pthread_self();
pthread_mutex_lock(&g_errs.lock);
for ( uint32_t i = 0; i < g_errs.num; i++ )
{
if ( pthread_equal(g_errs.tids[i], tid) )
{
retval = g_errs.errs[i];
goto release_lock;
}
}
release_lock:
pthread_mutex_unlock(&g_errs.lock);
return retval;
}
void
raise_runtime_error(struct error_info* ei)
{
pthread_t tid = pthread_self();
pthread_mutex_lock(&g_errs.lock);
for ( uint32_t i = 0; i < g_errs.num; i++ )
{
if ( pthread_equal(g_errs.tids[i], tid) )
{
// replace existing
memcpy(&g_errs.errs[i], ei, sizeof(error_info));
goto release_lock;
}
/*
* Dynamic cleanup to lower risk of resource exhaustion.
* Do it here, where we actually allocate the memory, forcing
* this to be processed at least whenever a new thread raises
* an error.
*/
if ( pthread_kill(g_errs.tids[i], 0) != 0 )
{
// doesn't exist, free memory. safe to adjust counter.
free(g_errs.errs[i]);
free(g_errs.tids[i]);
g_errs.num--;
}
}
/*
* first error reported by this thread id. allocate memory to hold its
* details, eventually free when thread no longer exists.
*/
struct error_info* newei = malloc(sizeof(struct error_info));
if ( newei == NULL )
{
goto release_lock;
}
pthread_t* newt = malloc(sizeof(pthread_t));
if ( newt == NULL )
{
free(newei);
goto release_lock;
}
// realloc-bits omitted
g_errs.errs[g_errs.num] = newei;
g_errs.tids[g_errs.num] = newt;
g_errs.num++;
release_lock:
pthread_mutex_unlock(&g_errs.lock);
}
... can I disable the ability for thread ids to be reused at runtime?
No, you can't.
I'm writing a C program that needs good error handling. The code likes like this:
If(doWork("A")<0){
return -1;
}
If(doWork("B")<0){
undoWork("A");
return -1;
}
If(doWork("C")<0){
undoWork("A");
undoWork("B");
return -1;
}
return 0;
This code works but looks very messy, especially I have a long list of doWork(X) to call. Is there a better and cleaner approach to handle error in this case?
Some people, especially beginner-to-intermediate programmers, have a very idiosyncratic reaction to seeing goto in production code, but the usual idiom for sequential acquiring of resources and their intelligent release upon error is the following:
if(doWork("A") < 0)
goto errA;
if(doWork("B") < 0)
goto errB;
if(doWork("C") < 0)
goto errC;
/* success! */
return 0;
/* Error handling / releasing resources section */
errC:
undoWork("B");
errB:
undoWork("A");
errA:
return -1;
You will see plenty of examples in system code, e.g. in the linux kernel.
Being the same task doWork, you can probably define a linked list or vector of jobs and pass that as a parameter to doWork, append the corresponding information to this list inside the function, and only call undoWork once:
If(doWork("A", &jobs)<0){
return -1;
}
If(doWork("B", &jobs)<0){
undoWork(jobs);
return -1;
}
If(doWork("C", &jobs)<0){
undoWork(jobs);
return -1;
}
return 0;
This way, your logic will not become overly complicated, no matter the combination of jobs to be undone.
The advantage, compared to #twain249's solution, is that the function decides whether a job is added to the list or not, so you've got a nice isolation, modularity.
You can of course combine some form of an interable data structure with this, to further reduce the amount of repetitive code:
for(i=0; i < jobdata.size; i++) {
If(doWork(jobdata[i], &jobs)<0){
undowork(jobs);
return -1;
}
}
As you can notice, data structure design plays an important role in algorithm design, usually a much more important one than one usually thinks.
There could be thousands of jobs, the code will remain a four-liner.
Probably not. Newer languages like C++ and C# favor exceptions to help improve situations just like this.
Perhaps you could have a table that somehow indicated which tasks you've done and undo those. But I really think that would make your code more complex and not less.
Also note that, while there are some pretty strong feelings about using goto, there are in fact times when that can simplify structures like this.
if it's possible to store all things you have to call doWork on in an array then you could shorten the code significantly something like.
int i = 0;
int len = MAX_NUM; //set to the value of calls
int error = 0;
for(i = 0; i < len; i++) {
if(doWork(a[i]) < 0) {
error = 1;
break;
}
}
if(error) {
for(int j = 0; j < i; i++) {
undoWork(a[j]);
}
return -1;
}
If you don't have a super long list, you can approach it this way.
if (dowork("A") >=0) {
if (dowork("B") >=0) {
if (dowork("C") >=0) {
if (dowork("D") >=0) return 0;
undowork("C"); }
undowork("B"); }
undowork("A"); }
return -1;
There is also another widely used approach based on a single pass loop that is clear and doesn't require goto. It implies though that Undo functions correctly handle both work that was done and that was not.
do
{
if(doWork("A")<0)
break;
if(doWork("B")<0)
break;
if(doWork("C")<0)
break;
return 0;
}
while(0);
undoWork("A");
undoWork("B");
undoWork("C");
return -1;