static void* thread_loop(void *arg) { threadpool_t *pool = (threadpool_t*)arg; task_t *t = NULL; struct timespec ts; struct timeval tv; int ret; int tosignal; while (!pool->exit) { Pthread_mutex_lock(&pool->mutex); gettimeofday(&tv, NULL); ts.tv_sec = tv.tv_sec + POOL_MAX_IDLE; ts.tv_nsec = tv.tv_usec * 1000; while (pool->task_queue.len == 0) { ret = Pthread_cond_timedwait(&pool->cond, &pool->mutex, &ts); if (ret == 0) { if (pool->exit) { goto EXIT; } break; } else if (ret == ETIMEDOUT) { goto EXIT; } } --pool->threads_idle; t = heap_remove(&pool->task_queue, 0); tosignal = (pool->task_queue.len == 0) ? 1 : 0; Pthread_mutex_unlock(&pool->mutex); if (tosignal) { Pthread_cond_broadcast(&pool->task_over_cond); } if (t) { t->func(t->arg); free(t); } Pthread_mutex_lock(&pool->mutex); ++pool->threads_idle; Pthread_mutex_unlock(&pool->mutex); } Pthread_mutex_lock(&pool->mutex); EXIT: --pool->threads_idle; tosignal = --pool->threads_num ? 0 : 1; Pthread_mutex_unlock(&pool->mutex); if (tosignal) { Pthread_cond_broadcast(&pool->exit_cond); } return NULL; }
void * Consumer(void *v) { struct thread_data *data = (struct thread_data *)v; unsigned sum = 0; int n, item; int waits = 0; int l = maxbuflen - 1; for (n = 0; ; ++n) { Pthread_mutex_lock(&buf_mutex); while (buflen == 0) { if (eof) { Pthread_mutex_unlock(&buf_mutex); goto done; } ++waits; Pthread_cond_wait(&empty_cond, &buf_mutex); } item = buf[--buflen]; if (buflen == l) Pthread_cond_broadcast(&full_cond); Pthread_mutex_unlock(&buf_mutex); ConsumeItem(item, &sum); } done: data->sum = sum; printf("Consumer %d exit, %d items received, %d waits\n", data->no, n, waits); return data; }
int threadpool_add_task(threadpool_t *pool, void (*func)(void*), void *arg, int priority) { int tosignal = 0; task_t *tq = (task_t *)calloc(1, sizeof(*tq)); if (!tq) { return -1; } tq->func = func; tq->arg = arg; tq->priority = priority; Pthread_mutex_lock(&pool->mutex); if (pool->threads_idle == 0 && pool->threads_num < pool->threads_max) { threadpool_thread_create(pool); ++pool->threads_idle; ++pool->threads_num; } tosignal = (pool->task_queue.len == 0) ? 1 : 0; if (heap_insert(&pool->task_queue, tq) != 0) { free(tq); Pthread_mutex_unlock(&pool->mutex); return -1; } Pthread_mutex_unlock(&pool->mutex); if (tosignal) { Pthread_cond_broadcast(&pool->cond); } return 0; }
void * Producer(void *v) { struct thread_data *data = (struct thread_data *)v; unsigned seed = data->seed; int n; unsigned item, sum; int waits = 0; data->sum = 0; for (n = 0; n < num_items; ++n) { pthread_testcancel(); sum = 0; item = ProduceItem(&seed, &sum); pthread_cleanup_push(pthread_mutex_unlock, &buf_mutex); Pthread_mutex_lock(&buf_mutex); while (buflen == maxbuflen) { ++waits; Pthread_cond_wait(&full_cond, &buf_mutex); } buf[buflen++] = item; data->sum += sum; if (buflen == 1) Pthread_cond_broadcast(&empty_cond); pthread_cleanup_pop(1); } printf("Producer %d exit, %d waits\n", data->no, waits); return data; }
void * Producer(void *v) { struct producer *p = (struct producer *)v; struct consumer *c; struct packet *pa, *old; unsigned seed = p->seed; int n, k, cons; unsigned sum = 0; int waits = 0; int more = 1; int item_cnt = 0; cons = seed % num_consumers; for (n = 0; more; ++n) { /* Hole Packet aus lokaler emptyPacketQueue */ Pthread_mutex_lock(&p->queue_mutex); while (!p->emptyPacketQueue) { ++waits; Pthread_cond_wait(&p->empty_cond, &p->queue_mutex); } pa = p->emptyPacketQueue; p->emptyPacketQueue = pa->next; Pthread_mutex_unlock(&p->queue_mutex); /* Fuelle Packet */ for (k = 0; k < buflen; ++k) { pa->buf[k] = ProduceItem(&seed, &sum); if (++item_cnt == num_items) { more = 0; ++k; break; } } pa->len = k; /* Versende Packet an Consumer cons */ c = consumers + cons; Pthread_mutex_lock(&c->queue_mutex); old = pa->next = c->fullPacketQueue; c->fullPacketQueue = pa; Pthread_mutex_unlock(&c->queue_mutex); if (!old) Pthread_cond_broadcast(&c->empty_cond); if (++cons == num_consumers) cons = 0; } p->sum = sum; printf("Producer %d exit, %d waits, %d packets\n", p->no, waits, n); return NULL; }
void * Consumer(void *v) { struct consumer *c = (struct consumer *)v; struct producer *p; struct packet *pa, *old; unsigned sum = 0; int n, k; int waits = 0; int item_cnt = 0; for (n = 0; ; ++n) { /* Hole Packet aus lokaler fullPacketQueue */ Pthread_mutex_lock(&c->queue_mutex); while (!c->fullPacketQueue) { if (c->eof) { Pthread_mutex_unlock(&c->queue_mutex); goto done; } ++waits; Pthread_cond_wait(&c->empty_cond, &c->queue_mutex); } pa = c->fullPacketQueue; c->fullPacketQueue = pa->next; Pthread_mutex_unlock(&c->queue_mutex); /* Verarbeite Packet */ for (k = 0; k < pa->len; ++k) ConsumeItem(pa->buf[k], &sum); item_cnt += pa->len; /* Stelle Packet zurueck in emptyPacketQueue des Owners */ p = producers + pa->owner; Pthread_mutex_lock(&p->queue_mutex); old = pa->next = p->emptyPacketQueue; p->emptyPacketQueue = pa; Pthread_mutex_unlock(&p->queue_mutex); if (!old) Pthread_cond_broadcast(&p->empty_cond); } done: c->sum = sum; printf("Consumer %d exit, %d items in %d packets received, %d waits\n", c->no, item_cnt, n, waits); return NULL; }
void threadpool_exit(threadpool_t *pool) { Pthread_mutex_lock(&pool->mutex); pool->exit = 1; Pthread_mutex_unlock(&pool->mutex); Pthread_cond_broadcast(&pool->cond); }
void wakeup() { Pthread_cond_broadcast(&c); }
int main(int argc, char **argv) { int n, e; unsigned prod_sum, cons_sum; struct thread_data *data; pthread_attr_t attr; int canceled = 0; pthread_t tid; if (argc > 1 && !strcmp("-", argv[1])) Error("usage: %s num_producers num_consumers " "num_items maxbuflen busy-loops", argv[0]); if (argc > 1) { num_producers = atoi(argv[1]); if (num_producers < 0) num_producers = 1; if (num_producers > MAXPRODUCERS) num_producers = MAXPRODUCERS; } if (argc > 2) { num_consumers = atoi(argv[2]); if (num_consumers < 0) num_consumers = 1; if (num_consumers > MAXCONSUMERS) num_consumers = MAXCONSUMERS; } if (argc > 3) { num_items = atoi(argv[3]); if (num_items < 0) num_items = 0; } if (argc > 4) { maxbuflen = atoi(argv[4]); if (maxbuflen < 0) maxbuflen = 1; if (maxbuflen > MAXBUFLEN) maxbuflen = MAXBUFLEN; } if (argc > 5) busy_loops = atoi(argv[5]); printf("num_producers %d num_consumers %d num_items %d " "maxbuflen %d busy-loops %d\n", num_producers, num_consumers, num_items, maxbuflen, busy_loops); num_items /= num_producers; /* items/producer */ sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); Pthread_sigmask(SIG_BLOCK, &sigmask, NULL); Pthread_attr_init(&attr); Pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); /* Starte die Producer */ for (n = 0; n < num_producers; ++n) { data = malloc(sizeof(struct thread_data)); if (!data) Error("malloc"); data->seed = n; data->no = n; producer_data[n] = data; Pthread_create(&producers[n], &attr, Producer, data); } /* Starte die Consumer */ for (n = 0; n < num_consumers; ++n) { data = malloc(sizeof(struct thread_data)); if (!data) Error("malloc"); data->no = n; Pthread_create(&consumers[n], &attr, Consumer, data); } Pthread_create(&tid, &attr, SigThread, NULL); /* Warte auf alle Producer */ prod_sum = 0; for (n = 0; n < num_producers; ++n) { Pthread_join(producers[n], (void **)&data); if (data == PTHREAD_CANCELED) canceled = 1; prod_sum += producer_data[n]->sum; } if (canceled) printf("*** program was cancelled\n"); /* setze eof und wecke consumer auf */ Pthread_mutex_lock(&buf_mutex); eof = 1; Pthread_mutex_unlock(&buf_mutex); Pthread_cond_broadcast(&empty_cond); /* Warte auf alle Consumer */ cons_sum = 0; for (n = 0; n < num_consumers; ++n) { Pthread_join(consumers[n], (void **)&data); cons_sum += data->sum; } printf("prot_sum %u cons_sum %u\n", prod_sum, cons_sum); if (cons_sum != prod_sum) printf("ERROR\n"); return 0; }
void* work_loop(void* args){ worker_p mine = (worker_p)args; crew_p crew = mine->crew; struct stat file_stat; struct dirent *entry; work_p work; entry = (struct dirent*)malloc(sizeof(struct dirent)+name_max); Pthread_mutex_lock(&crew->mutex); while(crew->work_cnt==0){ Pthread_cond_wait(&crew->go,&crew->mutex); } Pthread_mutex_unlock(&crew->mutex); while(1){ Pthread_mutex_lock(&crew->mutex); while(crew->first_work==NULL) Pthread_cond_wait(&crew->go,&crew->mutex); printf("woker %d works on :#%lx ,conunt is %d\n", mine->index,crew->first_work,crew->work_cnt); work = crew->first_work; crew->first_work = work->next; if(crew->first_work==NULL) crew->last_work = NULL; printf("woker %d took #%lx ,leaave first is #%lx last is #%lx\n", mine->index,work,crew->first_work,crew->last_work); Pthread_mutex_unlock(&crew->mutex); if(lstat(work->path,&file_stat)<0){ printf("%s error: %s\n",work->path,strerror(errno)); } if(S_ISLNK(file_stat.st_mode)){ printf("%s is a link\n", work->path); } else if (S_ISDIR(file_stat.st_mode)){ DIR* directory = opendir(work->path); struct dirent* result; if(directory==NULL){ fprintf(stderr, "open %s errro:%s\n", work->path,strerror(errno)); continue; } while(1){ int status = readdir_r(directory,entry,&result); if(status!=0){ fprintf(stderr, "unable to open %s,error:%s\n", work->path,strerror(status)); break; } if(result==NULL) break; if(strcmp(entry->d_name,".")==0||strcmp(entry->d_name,"..")==0) continue; work_p new_work= (work_p)malloc(sizeof(work_t)); new_work->string = work->string; new_work->path = (char*) malloc(path_max); strcpy(new_work->path,work->path); strcat(new_work->path,"/"); strcat(new_work->path,entry->d_name); new_work->next= NULL; Pthread_mutex_lock(&crew->mutex); if(crew->first_work==NULL){ crew->first_work=new_work; crew->last_work = new_work; }else{ crew->last_work->next = new_work; crew->last_work = new_work; } crew->work_cnt++; Pthread_cond_signal(&crew->go); Pthread_mutex_unlock(&crew->mutex); } closedir(directory); } else if (S_ISREG(file_stat.st_mode)){ FILE* file; char buf[MAXLINE],*fbuf; if((file = fopen(work->path,"r"))==NULL){ fprintf(stderr, "can not open %s:%s\n", work->path,strerror(errno)); continue; } else{ while(1){ if((fbuf= fgets(buf,MAXLINE,file))==NULL){ if(feof(file)) break; else if(ferror(file)){ fprintf(stderr, "read %s error:%s\n", work->path,strerror(errno)); break; } } if(strstr(buf,work->string)!=NULL){ printf("found %s in %s\n",work->string,work->path); break; } } fclose(file); } } else{ fprintf(stderr, "%s's type is %s\n", work->path,S_ISFIFO(file_stat.st_mode)?"FIFO": S_ISCHR(file_stat.st_mode)?"CHAR": S_ISBLK(file_stat.st_mode)?"BLK": S_ISSOCK(file_stat.st_mode)?"SOCK":"unknown"); } free(work->path); free(work); Pthread_mutex_lock(&crew->mutex); crew->work_cnt--; if(crew->work_cnt<=0){ Pthread_cond_broadcast(&crew->done); Pthread_mutex_unlock(&crew->mutex); break; } Pthread_mutex_unlock(&crew->mutex); } free(entry); return NULL; }
int main(int argc, char **argv) { int n, k, e; unsigned prod_sum, cons_sum; pthread_attr_t attr; struct packet *p; int packets_per_producer; if (argc > 1 && !strcmp("-", argv[1])) Error("usage: %s num_producers num_consumers " "num_items buflen busy-loops", argv[0]); if (argc > 1) { num_producers = atoi(argv[1]); if (num_producers < 0) num_producers = 1; if (num_producers > MAXPRODUCERS) num_producers = MAXPRODUCERS; } if (argc > 2) { num_consumers = atoi(argv[2]); if (num_consumers < 0) num_consumers = 1; if (num_consumers > MAXCONSUMERS) num_consumers = MAXCONSUMERS; } if (argc > 3) { num_items = atoi(argv[3]); if (num_items < 0) num_items = 0; } if (argc > 4) { buflen = atoi(argv[4]); if (buflen < 1) buflen = 1; } if (argc > 5) busy_loops = atoi(argv[5]); printf("num_producers %d num_consumers %d num_items %d " "buflen %d busy-loops %d\n", num_producers, num_consumers, num_items, buflen, busy_loops); num_items /= num_producers; /* items/producer */ Pthread_attr_init(&attr); Pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); /* Producer Datenstruktur */ packets_per_producer = (num_producers + num_consumers) * 2; for (n = 0; n < num_producers; ++n) { Pthread_mutex_init(&producers[n].queue_mutex, NULL); Pthread_cond_init(&producers[n].empty_cond, NULL); producers[n].seed = n; producers[n].no = n; producers[n].emptyPacketQueue = NULL; for (k = 0; k < packets_per_producer; ++k) { p = malloc(sizeof(struct packet) + (buflen - 1) * sizeof(unsigned)); if (!p) Error("malloc"); p->owner = n; p->next = producers[n].emptyPacketQueue; producers[n].emptyPacketQueue = p; } } /* Consumer Datenstruktur */ for (n = 0; n < num_consumers; ++n) { Pthread_mutex_init(&consumers[n].queue_mutex, NULL); Pthread_cond_init(&consumers[n].empty_cond, NULL); consumers[n].no = n; consumers[n].eof = 0; consumers[n].fullPacketQueue = NULL; } /* Starte die Producer */ for (n = 0; n < num_producers; ++n) Pthread_create(&producers[n].tid, &attr, Producer, &producers[n]); /* Starte die Consumer */ for (n = 0; n < num_consumers; ++n) Pthread_create(&consumers[n].tid, &attr, Consumer, &consumers[n]); /* Warte auf alle Producer */ prod_sum = 0; for (n = 0; n < num_producers; ++n) { Pthread_join(producers[n].tid, NULL); prod_sum += producers[n].sum; } /* setze eof und wecke consumer auf */ for (n = 0; n < num_consumers; ++n) { Pthread_mutex_lock(&consumers[n].queue_mutex); consumers[n].eof = 1; Pthread_mutex_unlock(&consumers[n].queue_mutex); Pthread_cond_broadcast(&consumers[n].empty_cond); } /* Warte auf alle Consumer */ cons_sum = 0; for (n = 0; n < num_consumers; ++n) { Pthread_join(consumers[n].tid, NULL); cons_sum += consumers[n].sum; } printf("prot_sum %u cons_sum %u\n", prod_sum, cons_sum); if (cons_sum != prod_sum) printf("ERROR\n"); return 0; }