thread_task.c (2976B)
1 /* Written by Kris Maglione <maglione.k at Gmail> */ 2 /* Public domain */ 3 #include <errno.h> 4 #include <stdlib.h> 5 #include <unistd.h> 6 #include <task.h> 7 #include "ixp_local.h" 8 9 static IxpThread ixp_task; 10 11 /** 12 * Function: ixp_taskinit 13 * 14 * This function initializes libixp for use in multithreaded 15 * programs using the libtask threading system. When using libixp in 16 * such programs, this function must be called before any other 17 * libixp functions. 18 * 19 * This function is part of libixp_task, which is part of the libixp 20 * distribution, but is not built by default unless enabled in 21 * config.mk. 22 */ 23 int 24 ixp_taskinit() { 25 ixp_thread = &ixp_task; 26 return 0; 27 } 28 29 static char* 30 errbuf(void) { 31 void **p; 32 33 p = taskdata(); 34 if(*p == nil) 35 *p = emallocz(IXP_ERRMAX); 36 return *p; 37 } 38 39 /* Mutex */ 40 static int 41 initmutex(IxpMutex *m) { 42 m->aux = emallocz(sizeof(QLock)); 43 return 0; 44 } 45 46 static void 47 mdestroy(IxpMutex *m) { 48 free(m->aux); 49 m->aux = nil; 50 } 51 52 static void 53 mlock(IxpMutex *m) { 54 qlock(m->aux); 55 } 56 57 static int 58 mcanlock(IxpMutex *m) { 59 return canqlock(m->aux); 60 } 61 62 static void 63 munlock(IxpMutex *m) { 64 qunlock(m->aux); 65 } 66 67 /* RWLock */ 68 static int 69 initrwlock(IxpRWLock *rw) { 70 rw->aux = emallocz(sizeof(RWLock)); 71 return 0; 72 } 73 74 static void 75 rwdestroy(IxpRWLock *rw) { 76 free(rw->aux); 77 rw->aux = nil; 78 } 79 80 static void 81 _rlock(IxpRWLock *rw) { 82 rlock(rw->aux); 83 } 84 85 static int 86 _canrlock(IxpRWLock *rw) { 87 return canrlock(rw->aux); 88 } 89 90 static void 91 _wlock(IxpRWLock *rw) { 92 wlock(rw->aux); 93 } 94 95 static int 96 _canwlock(IxpRWLock *rw) { 97 return canwlock(rw->aux); 98 } 99 100 static void 101 _runlock(IxpRWLock *rw) { 102 runlock(rw->aux); 103 } 104 105 static void 106 _wunlock(IxpRWLock *rw) { 107 wunlock(rw->aux); 108 } 109 110 /* Rendez */ 111 static int 112 initrendez(IxpRendez *r) { 113 r->aux = emallocz(sizeof(Rendez)); 114 return 0; 115 } 116 117 static void 118 rdestroy(IxpRendez *r) { 119 free(r->aux); 120 r->aux = nil; 121 } 122 123 static void 124 rsleep(IxpRendez *r) { 125 Rendez *rz; 126 127 rz = r->aux; 128 rz->l = r->mutex->aux; 129 tasksleep(rz); 130 } 131 132 static int 133 rwake(IxpRendez *r) { 134 Rendez *rz; 135 136 rz = r->aux; 137 rz->l = r->mutex->aux; 138 return taskwakeup(rz); 139 } 140 141 static int 142 rwakeall(IxpRendez *r) { 143 Rendez *rz; 144 145 rz = r->aux; 146 rz->l = r->mutex->aux; 147 return taskwakeupall(rz); 148 } 149 150 /* Yielding IO */ 151 static ssize_t 152 _read(int fd, void *buf, size_t size) { 153 fdnoblock(fd); 154 return fdread(fd, buf, size); 155 } 156 157 static ssize_t 158 _write(int fd, const void *buf, size_t size) { 159 fdnoblock(fd); 160 return fdwrite(fd, (void*)buf, size); 161 } 162 163 static IxpThread ixp_task = { 164 /* Mutex */ 165 .initmutex = initmutex, 166 .lock = mlock, 167 .canlock = mcanlock, 168 .unlock = munlock, 169 .mdestroy = mdestroy, 170 /* RWLock */ 171 .initrwlock = initrwlock, 172 .rlock = _rlock, 173 .canrlock = _canrlock, 174 .wlock = _wlock, 175 .canwlock = _canwlock, 176 .runlock = _runlock, 177 .wunlock = _wunlock, 178 .rwdestroy = rwdestroy, 179 /* Rendez */ 180 .initrendez = initrendez, 181 .sleep = rsleep, 182 .wake = rwake, 183 .wakeall = rwakeall, 184 .rdestroy = rdestroy, 185 /* Other */ 186 .errbuf = errbuf, 187 .read = _read, 188 .write = _write, 189 .select = select, /* wrong */ 190 }; 191