ref: bc2a7c9a7410261c1679d088e01bbf19bf4dd62e
dir: /main8.c/
#include <u.h> #include <libc.h> #include <thread.h> #include <draw.h> #include <memdraw.h> typedef struct Ttask Ttask; typedef struct Tpool Tpool; struct Ttask { void (*fn)(void*); void *arg; }; struct Tpool { ulong nprocs; Channel *subq; /* task submission queue */ }; void threadloop(void *arg) { Tpool *pool; Ttask *task; pool = arg; while((task = recvp(pool->subq)) != nil) task->fn(task->arg); } Tpool * mkthreadpool(ulong nprocs) { Tpool *tp; tp = malloc(sizeof *tp); memset(tp, 0, sizeof *tp); tp->nprocs = nprocs; tp->subq = chancreate(sizeof(void*), nprocs); while(nprocs--) proccreate(threadloop, tp, mainstacksize); return tp; } void threadpoolexec(Tpool *tp, void (*fn)(void*), void *arg) { Ttask *t; t = malloc(sizeof *t); t->fn = fn; t->arg = arg; sendp(tp->subq, t); } typedef struct Targs Targs; struct Targs { Memimage *i; ulong off; ulong len; Channel *done; /* task completion signal */ }; void fillpix(void *arg) { Targs *imgop; Point p; ulong *fb, *fbb, *fbe, pix; double α; imgop = arg; fb = (ulong*)byteaddr(imgop->i, ZP); fbb = fb + imgop->off; fbe = fbb + imgop->len; while(fbb < fbe){ p.x = (fbb-fb)%Dx(imgop->i->r); p.y = (fbb-fb)/Dx(imgop->i->r); α = atan2(p.y, p.x); pix = α*25523UL*25523UL/* + truerand()*/; *fbb++ = pix|0xFF<<24; } nbsend(imgop->done, nil); } void usage(void) { fprint(2, "usage: %s [-t] [-n nprocs] [-c count]\n", argv0); exits(nil); } void threadmain(int argc, char *argv[]) { static int W = 1000, H = 1000; Tpool *pool; Targs *t; Memimage *img; int i, stride; int threaded; int nprocs; int cnt; threaded = 0; nprocs = 8; cnt = 100; ARGBEGIN{ case 't': threaded++; break; case 'n': nprocs = strtoul(EARGF(usage()), nil, 0); break; case 'c': cnt = strtoul(EARGF(usage()), nil, 0); break; default: usage(); }ARGEND; if(argc != 0) usage(); if(memimageinit() != 0) sysfatal("memimageinit: %r"); img = allocmemimage(Rect(0,0,W,H), XRGB32); t = malloc(nprocs*sizeof(*t)); stride = W*H/nprocs; if(threaded){ pool = mkthreadpool(nprocs); while(cnt--) for(i = 0; i < nprocs; i++){ t[i] = (Targs){ img, i*stride, i == nprocs-1? W*H-i*stride: stride, chancreate(sizeof(void*), 1) }; threadpoolexec(pool, fillpix, &t[i]); } for(i = 0; i < nprocs; i++) recvp(t[i].done); writememimage(1, img); threadexitsall(nil); } while(cnt--) for(i = 0; i < nprocs; i++){ t[i] = (Targs){ img, i*stride, i == nprocs-1? W*H-i*stride: stride, chancreate(sizeof(void*), 1) }; fillpix(&t[i]); } writememimage(1, img); exits(nil); }