diff options
| -rw-r--r-- | src/arena.c | 24 | ||||
| -rw-r--r-- | src/encryption.c | 25 | ||||
| -rw-r--r-- | src/ll.c | 43 | ||||
| -rw-r--r-- | src/scanner.c | 6 | ||||
| -rw-r--r-- | src/shared.c | 31 | ||||
| -rw-r--r-- | src/shared.h | 2 | ||||
| -rw-r--r-- | src/threadpool.c | 63 | ||||
| -rw-r--r-- | src/threadpool.h | 30 |
8 files changed, 106 insertions, 118 deletions
diff --git a/src/arena.c b/src/arena.c index 40c72d5..8f32064 100644 --- a/src/arena.c +++ b/src/arena.c | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | #include "arena.h" | 1 | #include "arena.h" |
| 2 | #include "shared.h" | 2 | #include "shared.h" |
| 3 | 3 | ||
| 4 | #include <asm-generic/errno-base.h> | ||
| 4 | #include <stddef.h> | 5 | #include <stddef.h> |
| 5 | #include <stdint.h> | 6 | #include <stdint.h> |
| 6 | #include <stdlib.h> | 7 | #include <stdlib.h> |
| @@ -26,6 +27,8 @@ typedef struct arena { | |||
| 26 | } arena; | 27 | } arena; |
| 27 | 28 | ||
| 28 | arenanode * arenanode_init(size_t bytes) { | 29 | arenanode * arenanode_init(size_t bytes) { |
| 30 | if(bytes < 1) ERRRET(EINVAL, NULL); | ||
| 31 | |||
| 29 | arenanode *an = VALLOC(1, sizeof(*an)); | 32 | arenanode *an = VALLOC(1, sizeof(*an)); |
| 30 | if(!an) | 33 | if(!an) |
| 31 | return NULL; | 34 | return NULL; |
| @@ -47,10 +50,8 @@ arenanode * arenanode_init(size_t bytes) { | |||
| 47 | } | 50 | } |
| 48 | 51 | ||
| 49 | arena * arena_init(size_t bytes) { | 52 | arena * arena_init(size_t bytes) { |
| 50 | if(!ISPOWOF2(MEM_ALIGN_BYTES)) | 53 | if(!ISPOWOF2(MEM_ALIGN_BYTES)) XALLOC_EXIT("<arena_init> \"MEM_ALIGN_BYTES\" is not a power of 2. Refusing to create a new arena", ); |
| 51 | XALLOC_EXIT("<arena_init> \"MEM_ALIGN_BYTES\" is not a power of 2. Refusing to create a new arena", ); | 54 | if(bytes < 1) ERRRET(EINVAL, NULL); |
| 52 | if(bytes < 1) | ||
| 53 | RETURNWERR(EINVAL, NULL); | ||
| 54 | 55 | ||
| 55 | arena *a = VALLOC(1, sizeof(arena)); | 56 | arena *a = VALLOC(1, sizeof(arena)); |
| 56 | if(!a) | 57 | if(!a) |
| @@ -73,12 +74,9 @@ arena * arena_init(size_t bytes) { | |||
| 73 | } | 74 | } |
| 74 | 75 | ||
| 75 | void * arena_alloc(arena * const arena, size_t bytes) { | 76 | void * arena_alloc(arena * const arena, size_t bytes) { |
| 76 | if(!ISPOWOF2(MEM_ALIGN_BYTES)) | 77 | if(!ISPOWOF2(MEM_ALIGN_BYTES)) XALLOC_EXIT("<arena_alloc> \"MEM_ALIGN_BYTES\" is not a power of 2. Refusing to allocate any memory", ); |
| 77 | XALLOC_EXIT("<arena_alloc> \"MEM_ALIGN_BYTES\" is not a power of 2. Refusing to allocate any memory", ); | 78 | if(!arena) ERRRET(EINVAL, NULL); |
| 78 | if(!arena) | 79 | if(bytes > arena->node_memspace) ERRRET(ENOMEM, NULL); |
| 79 | RETURNWERR(EINVAL, NULL); | ||
| 80 | if(bytes > arena->node_memspace) | ||
| 81 | RETURNWERR(ENOMEM, NULL); | ||
| 82 | 80 | ||
| 83 | if(bytes > ((arena->current)->allocated - (arena->current)->used)) { | 81 | if(bytes > ((arena->current)->allocated - (arena->current)->used)) { |
| 84 | arenanode *new = arenanode_init(arena->node_memspace); | 82 | arenanode *new = arenanode_init(arena->node_memspace); |
| @@ -133,10 +131,8 @@ void * simplearena_alloc(simplearena * const a, size_t bytes) { | |||
| 133 | // The criteria to allocate new memory in arena_alloc is 'bytes > ((a->current)->allocated - (a->current)->used)', so if this | 131 | // The criteria to allocate new memory in arena_alloc is 'bytes > ((a->current)->allocated - (a->current)->used)', so if this |
| 134 | // is true, just return NULL & set errno | 132 | // is true, just return NULL & set errno |
| 135 | 133 | ||
| 136 | if(!a) | 134 | if(!a) ERRRET(EINVAL, NULL); |
| 137 | RETURNWERR(EINVAL, NULL); | 135 | if(bytes > ((a->current)->allocated - (a->current)->used)) ERRRET(ENOMEM, NULL); |
| 138 | if(bytes > ((a->current)->allocated - (a->current)->used)) | ||
| 139 | RETURNWERR(ENOMEM, NULL); | ||
| 140 | 136 | ||
| 141 | return arena_alloc(a, bytes); | 137 | return arena_alloc(a, bytes); |
| 142 | } | 138 | } |
diff --git a/src/encryption.c b/src/encryption.c index 3530eed..3bf9dd4 100644 --- a/src/encryption.c +++ b/src/encryption.c | |||
| @@ -1,3 +1,5 @@ | |||
| 1 | // TODO: Go back and make sure every function has proper error handling | ||
| 2 | |||
| 1 | #define _GNU_SOURCE | 3 | #define _GNU_SOURCE |
| 2 | 4 | ||
| 3 | #include "encryption.h" | 5 | #include "encryption.h" |
| @@ -70,12 +72,13 @@ void checksodium(void) { | |||
| 70 | #endif | 72 | #endif |
| 71 | 73 | ||
| 72 | int maketmp(const char * const dest) { | 74 | int maketmp(const char * const dest) { |
| 73 | if(!dest) | 75 | if(!dest) ERRRET(EINVAL, -1); |
| 74 | RETURNWERR(EINVAL, -1); | ||
| 75 | return open(dest, (O_TMPFILE | O_WRONLY | O_CLOEXEC | O_SYNC), (S_IRUSR | S_IWUSR)); | 76 | return open(dest, (O_TMPFILE | O_WRONLY | O_CLOEXEC | O_SYNC), (S_IRUSR | S_IWUSR)); |
| 76 | } | 77 | } |
| 77 | 78 | ||
| 78 | int linkto(const char * const target, int tgfd) { | 79 | int linkto(const char * const target, int tgfd) { |
| 80 | if(!target) ERRRET(EINVAL, -1); | ||
| 81 | |||
| 79 | char *path = NULL; | 82 | char *path = NULL; |
| 80 | asprintf(&path, "/proc/self/fd/%d", tgfd); | 83 | asprintf(&path, "/proc/self/fd/%d", tgfd); |
| 81 | if(!path) | 84 | if(!path) |
| @@ -129,11 +132,11 @@ int decryptto(const char * const encrypted, const char * const target, const uns | |||
| 129 | #endif | 132 | #endif |
| 130 | 133 | ||
| 131 | if(!encrypted) | 134 | if(!encrypted) |
| 132 | RETURNWERR(EINVAL, -1); | 135 | ERRRET(EINVAL, -1); |
| 133 | if(!target) | 136 | if(!target) |
| 134 | RETURNWERR(EINVAL, -1); | 137 | ERRRET(EINVAL, -1); |
| 135 | if(!key) | 138 | if(!key) |
| 136 | RETURNWERR(EINVAL, -1); | 139 | ERRRET(EINVAL, -1); |
| 137 | 140 | ||
| 138 | FILE *src, *dst; | 141 | FILE *src, *dst; |
| 139 | if(!(src = fopen(encrypted, "rb"))) | 142 | if(!(src = fopen(encrypted, "rb"))) |
| @@ -174,11 +177,11 @@ int encrypttofile(FILE *src, FILE *dst, const unsigned char key[crypto_secretstr | |||
| 174 | #endif | 177 | #endif |
| 175 | 178 | ||
| 176 | if(!src) | 179 | if(!src) |
| 177 | RETURNWERR(EINVAL, -1); | 180 | ERRRET(EINVAL, -1); |
| 178 | if(!dst) | 181 | if(!dst) |
| 179 | RETURNWERR(EINVAL, -1); | 182 | ERRRET(EINVAL, -1); |
| 180 | if(!key) | 183 | if(!key) |
| 181 | RETURNWERR(EINVAL, -1); | 184 | ERRRET(EINVAL, -1); |
| 182 | 185 | ||
| 183 | // Write the header | 186 | // Write the header |
| 184 | crypto_secretstream_xchacha20poly1305_init_push(&state, header, key); | 187 | crypto_secretstream_xchacha20poly1305_init_push(&state, header, key); |
| @@ -217,11 +220,11 @@ int decrypttofile(FILE *src, FILE *dst, const unsigned char key[crypto_secretstr | |||
| 217 | #endif | 220 | #endif |
| 218 | 221 | ||
| 219 | if(!src) | 222 | if(!src) |
| 220 | RETURNWERR(EINVAL, -1); | 223 | ERRRET(EINVAL, -1); |
| 221 | if(!dst) | 224 | if(!dst) |
| 222 | RETURNWERR(EINVAL, -1); | 225 | ERRRET(EINVAL, -1); |
| 223 | if(!key) | 226 | if(!key) |
| 224 | RETURNWERR(EINVAL, -1); | 227 | ERRRET(EINVAL, -1); |
| 225 | 228 | ||
| 226 | // Read the header | 229 | // Read the header |
| 227 | if(fread(header, 1, sizeof(header), src) < sizeof(header)) | 230 | if(fread(header, 1, sizeof(header), src) < sizeof(header)) |
| @@ -66,15 +66,12 @@ void dlinkedlist_free(void *dll) { | |||
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | int dlinkedlist_size(const dlinkedlist * const ll) { | 68 | int dlinkedlist_size(const dlinkedlist * const ll) { |
| 69 | if(!ll) | 69 | if(!ll) ERRRET(EINVAL, -1); |
| 70 | RETURNWERR(EINVAL, -1); | ||
| 71 | |||
| 72 | return ll->size; | 70 | return ll->size; |
| 73 | } | 71 | } |
| 74 | 72 | ||
| 75 | int dlinkedlist_handlefirstnode(dlinkedlist * const ll, void *data, dll_freecb fcb) { | 73 | int dlinkedlist_handlefirstnode(dlinkedlist * const ll, void *data, dll_freecb fcb) { |
| 76 | if(!ll) | 74 | if(!ll) ERRRET(EINVAL, 1); |
| 77 | RETURNWERR(EINVAL, 1); | ||
| 78 | if(ll->size > 0) | 75 | if(ll->size > 0) |
| 79 | return 1; | 76 | return 1; |
| 80 | 77 | ||
| @@ -92,10 +89,7 @@ int dlinkedlist_handlefirstnode(dlinkedlist * const ll, void *data, dll_freecb f | |||
| 92 | } | 89 | } |
| 93 | 90 | ||
| 94 | int dlinkedlist_xxxend(dlinkedlist * const ll, void *data, dll_freecb fcb, char op) { | 91 | int dlinkedlist_xxxend(dlinkedlist * const ll, void *data, dll_freecb fcb, char op) { |
| 95 | if(!ll) | 92 | if(!ll || (op != 'a' && op != 'p')) ERRRET(EINVAL, 1); |
| 96 | RETURNWERR(EINVAL, 1); | ||
| 97 | if(op != 'a' && op != 'p') | ||
| 98 | RETURNWERR(EINVAL, 1); | ||
| 99 | 93 | ||
| 100 | int handleret; | 94 | int handleret; |
| 101 | if((handleret = dlinkedlist_handlefirstnode(ll, data, fcb)) == 0) | 95 | if((handleret = dlinkedlist_handlefirstnode(ll, data, fcb)) == 0) |
| @@ -126,6 +120,8 @@ int dlinkedlist_xxxend(dlinkedlist * const ll, void *data, dll_freecb fcb, char | |||
| 126 | ll->size++; | 120 | ll->size++; |
| 127 | return 0; | 121 | return 0; |
| 128 | } | 122 | } |
| 123 | // TODO: Figure out where the memory leak gcc keeps complaining about is & fix it | ||
| 124 | |||
| 129 | 125 | ||
| 130 | int dlinkedlist_append(dlinkedlist * const ll, void *data, dll_freecb fcb) { | 126 | int dlinkedlist_append(dlinkedlist * const ll, void *data, dll_freecb fcb) { |
| 131 | return dlinkedlist_xxxend(ll, data, fcb, 'a'); | 127 | return dlinkedlist_xxxend(ll, data, fcb, 'a'); |
| @@ -136,10 +132,8 @@ int dlinkedlist_prepend(dlinkedlist * const ll, void *data, dll_freecb fcb) { | |||
| 136 | } | 132 | } |
| 137 | 133 | ||
| 138 | dllnode * dlinkedlist_getnode(const dlinkedlist * const ll, int index) { | 134 | dllnode * dlinkedlist_getnode(const dlinkedlist * const ll, int index) { |
| 139 | if(!ll) | 135 | if(!ll) ERRRET(EINVAL, NULL); |
| 140 | RETURNWERR(EINVAL, NULL); | 136 | if(index < 0 || index >= ll->size) ERRRET(EINVAL, NULL); |
| 141 | if(index < 0 || index >= ll->size) | ||
| 142 | RETURNWERR(EINVAL, NULL); | ||
| 143 | 137 | ||
| 144 | if(index == 0) | 138 | if(index == 0) |
| 145 | return ll->start; | 139 | return ll->start; |
| @@ -157,10 +151,8 @@ dllnode * dlinkedlist_getnode(const dlinkedlist * const ll, int index) { | |||
| 157 | } | 151 | } |
| 158 | 152 | ||
| 159 | int dlinkedlist_insert(dlinkedlist * const ll, void *data, dll_freecb fcb, int index) { | 153 | int dlinkedlist_insert(dlinkedlist * const ll, void *data, dll_freecb fcb, int index) { |
| 160 | if(!ll) | 154 | if(!ll) ERRRET(EINVAL, 1); |
| 161 | RETURNWERR(EINVAL, 1); | 155 | if(index < 0 || index >= ll->size) ERRRET(EINVAL, 1); |
| 162 | if(index < 0 || index >= ll->size) | ||
| 163 | RETURNWERR(EINVAL, 1); | ||
| 164 | 156 | ||
| 165 | // Handle the special cases of appending or prepending | 157 | // Handle the special cases of appending or prepending |
| 166 | if(index == 0) | 158 | if(index == 0) |
| @@ -188,10 +180,8 @@ int dlinkedlist_insert(dlinkedlist * const ll, void *data, dll_freecb fcb, int i | |||
| 188 | } | 180 | } |
| 189 | 181 | ||
| 190 | int dlinkedlist_remove(dlinkedlist * const ll, int index) { | 182 | int dlinkedlist_remove(dlinkedlist * const ll, int index) { |
| 191 | if(!ll) | 183 | if(!ll) ERRRET(EINVAL, 1); |
| 192 | RETURNWERR(EINVAL, 1); | 184 | if(index < 0 || index >= ll->size) ERRRET(EINVAL, 2); |
| 193 | if(index < 0 || index >= ll->size) | ||
| 194 | RETURNWERR(EINVAL, 2); | ||
| 195 | 185 | ||
| 196 | dllnode *current = dlinkedlist_getnode(ll, index); | 186 | dllnode *current = dlinkedlist_getnode(ll, index); |
| 197 | if(!current) | 187 | if(!current) |
| @@ -226,10 +216,7 @@ void* dlinkedlist_get(const dlinkedlist * const ll, int index) { | |||
| 226 | } | 216 | } |
| 227 | 217 | ||
| 228 | int dlinkedlist_foreach(dlinkedlist *ll, int (*callback)(void*)) { | 218 | int dlinkedlist_foreach(dlinkedlist *ll, int (*callback)(void*)) { |
| 229 | if(!ll) | 219 | if(!ll || callback == NULL) ERRRET(EINVAL, -1); |
| 230 | RETURNWERR(EINVAL, -1); | ||
| 231 | if(!callback) | ||
| 232 | RETURNWERR(EINVAL, -1); | ||
| 233 | 220 | ||
| 234 | for(dllnode *p = ll->start; p != NULL; p = p->next) | 221 | for(dllnode *p = ll->start; p != NULL; p = p->next) |
| 235 | callback(p->data); | 222 | callback(p->data); |
| @@ -238,10 +225,8 @@ int dlinkedlist_foreach(dlinkedlist *ll, int (*callback)(void*)) { | |||
| 238 | } | 225 | } |
| 239 | 226 | ||
| 240 | void * dlinkedlist_poplast(dlinkedlist *ll) { | 227 | void * dlinkedlist_poplast(dlinkedlist *ll) { |
| 241 | if(!ll) | 228 | if(!ll) ERRRET(EINVAL, NULL); |
| 242 | RETURNWERR(EINVAL, NULL); | 229 | if(dlinkedlist_isempty(ll)) ERRRET(ENODATA, NULL); |
| 243 | if(dlinkedlist_isempty(ll)) | ||
| 244 | RETURNWERR(ENODATA, NULL); | ||
| 245 | 230 | ||
| 246 | void *data = dlinkedlist_get(ll, ll->size - 1); | 231 | void *data = dlinkedlist_get(ll, ll->size - 1); |
| 247 | dlinkedlist_remove(ll, ll->size - 1); | 232 | dlinkedlist_remove(ll, ll->size - 1); |
diff --git a/src/scanner.c b/src/scanner.c index d20c714..ea35e3c 100644 --- a/src/scanner.c +++ b/src/scanner.c | |||
| @@ -11,12 +11,14 @@ | |||
| 11 | #include <error.h> | 11 | #include <error.h> |
| 12 | 12 | ||
| 13 | dlinkedlist * scandirlist(const char * const dir, int (*selector)(const struct dirent *), int (*cmp)(const struct dirent **, const struct dirent **)) { | 13 | dlinkedlist * scandirlist(const char * const dir, int (*selector)(const struct dirent *), int (*cmp)(const struct dirent **, const struct dirent **)) { |
| 14 | if(!dir || selector == NULL || cmp == NULL) ERRRET(EINVAL, NULL); | ||
| 15 | |||
| 14 | struct dirent **namelist = NULL; | 16 | struct dirent **namelist = NULL; |
| 15 | dlinkedlist *list = NULL; | 17 | dlinkedlist *list = NULL; |
| 16 | int numentries = -1; | 18 | int numentries = -1; |
| 17 | 19 | ||
| 18 | if((numentries = scandir(dir, &namelist, selector, cmp)) < 0) | 20 | if((numentries = scandir(dir, &namelist, selector, cmp)) < 0) |
| 19 | RETURNWERR(errno, NULL); | 21 | ERRRET(errno, NULL); |
| 20 | 22 | ||
| 21 | list = dlinkedlist_init(); | 23 | list = dlinkedlist_init(); |
| 22 | for(int i = 0; i < numentries; i++) | 24 | for(int i = 0; i < numentries; i++) |
| @@ -26,7 +28,7 @@ dlinkedlist * scandirlist(const char * const dir, int (*selector)(const struct d | |||
| 26 | free(namelist[j]); | 28 | free(namelist[j]); |
| 27 | 29 | ||
| 28 | free(namelist); | 30 | free(namelist); |
| 29 | RETURNWERR(errno, NULL); | 31 | ERRRET(errno, NULL); |
| 30 | } | 32 | } |
| 31 | free(namelist); | 33 | free(namelist); |
| 32 | 34 | ||
diff --git a/src/shared.c b/src/shared.c index 1d5aa7f..e83261c 100644 --- a/src/shared.c +++ b/src/shared.c | |||
| @@ -17,24 +17,23 @@ enum XALLOC_TYPE { | |||
| 17 | }; | 17 | }; |
| 18 | 18 | ||
| 19 | void * xalloc(size_t nmemb, size_t size, enum XALLOC_TYPE actype, void *ptr) { | 19 | void * xalloc(size_t nmemb, size_t size, enum XALLOC_TYPE actype, void *ptr) { |
| 20 | if(actype <= XALLOC_INVAL || actype >= XALLOC_2BIG) | 20 | if(actype <= XALLOC_INVAL || actype >= XALLOC_2BIG) ERRRET(EINVAL, NULL); |
| 21 | RETURNWERR(EINVAL, NULL); | ||
| 22 | 21 | ||
| 23 | void *mem = NULL; | 22 | void *mem = NULL; |
| 24 | switch(actype) { | 23 | switch(actype) { |
| 25 | case XALLOC_MALLOC: | 24 | case XALLOC_MALLOC: |
| 26 | mem = malloc(nmemb * size); | 25 | mem = malloc(nmemb * size); |
| 27 | break; | 26 | break; |
| 28 | 27 | ||
| 29 | case XALLOC_CALLOC: | 28 | case XALLOC_CALLOC: |
| 30 | mem = calloc(nmemb, size); | 29 | mem = calloc(nmemb, size); |
| 31 | break; | 30 | break; |
| 32 | 31 | ||
| 33 | case XALLOC_REALLOC: | 32 | case XALLOC_REALLOC: |
| 34 | mem = realloc(ptr, nmemb * size); | 33 | mem = realloc(ptr, nmemb * size); |
| 35 | break; | 34 | break; |
| 36 | 35 | ||
| 37 | default: | 36 | default: |
| 38 | XALLOC_EXIT("<xalloc> An unknown alloc type was passed, which shouldn't be possible", ); | 37 | XALLOC_EXIT("<xalloc> An unknown alloc type was passed, which shouldn't be possible", ); |
| 39 | } | 38 | } |
| 40 | 39 | ||
| @@ -61,7 +60,7 @@ int rwbuf(char **str, unsigned long int initsize, int fd) { | |||
| 61 | // Bytes read == 0, return 0 | 60 | // Bytes read == 0, return 0 |
| 62 | // Bytes read < 0, free string, return -1; | 61 | // Bytes read < 0, free string, return -1; |
| 63 | // When string hits capacity, double the capacity, and reallocate the string | 62 | // When string hits capacity, double the capacity, and reallocate the string |
| 64 | 63 | if(!str || initsize < 1) ERRRET(EINVAL, -1); | |
| 65 | const int ECODE = -100; | 64 | const int ECODE = -100; |
| 66 | 65 | ||
| 67 | char *lstr = NULL, *tmp = NULL; | 66 | char *lstr = NULL, *tmp = NULL; |
| @@ -118,6 +117,8 @@ int rwbuf(char **str, unsigned long int initsize, int fd) { | |||
| 118 | 117 | ||
| 119 | 118 | ||
| 120 | int wwbuf(int fd, const unsigned char *buf, int len) { | 119 | int wwbuf(int fd, const unsigned char *buf, int len) { |
| 120 | if(!buf || len <= 0) ERRRET(EINVAL, -1); | ||
| 121 | |||
| 121 | int total = 0; | 122 | int total = 0; |
| 122 | int left = len; | 123 | int left = len; |
| 123 | int n = -1; | 124 | int n = -1; |
| @@ -225,7 +226,7 @@ char * xdirname(const char * const path) { | |||
| 225 | 226 | ||
| 226 | 227 | ||
| 227 | int cleanup_init(cleanup *loc, fcallback callbacks[], void *arguments[], int size) { | 228 | int cleanup_init(cleanup *loc, fcallback callbacks[], void *arguments[], int size) { |
| 228 | if(!loc || !callbacks || !arguments || size <= 0) {errno = EINVAL; return -1;} | 229 | if(!loc || !callbacks || !arguments || size <= 0) ERRRET(EINVAL, -1); |
| 229 | 230 | ||
| 230 | loc->callbacks = callbacks; | 231 | loc->callbacks = callbacks; |
| 231 | loc->arguments = arguments; | 232 | loc->arguments = arguments; |
| @@ -237,8 +238,8 @@ int cleanup_init(cleanup *loc, fcallback callbacks[], void *arguments[], int siz | |||
| 237 | 238 | ||
| 238 | // registers if flag is NOT set | 239 | // registers if flag is NOT set |
| 239 | int cleanup_register(cleanup *loc, fcallback cb, void *arg) { | 240 | int cleanup_register(cleanup *loc, fcallback cb, void *arg) { |
| 240 | if(!loc || !cb) {errno = EINVAL; return -1;} | 241 | if(!loc || !cb) ERRRET(EINVAL, -1); |
| 241 | if(loc->used >= loc->size || loc->used < 0) {errno = ENOMEM; return -1;} | 242 | if(loc->used >= loc->size || loc->used < 0) ERRRET(ENOMEM, -1); |
| 242 | 243 | ||
| 243 | loc->callbacks[loc->used] = cb; | 244 | loc->callbacks[loc->used] = cb; |
| 244 | loc->arguments[loc->used] = arg; | 245 | loc->arguments[loc->used] = arg; |
| @@ -248,20 +249,18 @@ int cleanup_register(cleanup *loc, fcallback cb, void *arg) { | |||
| 248 | } | 249 | } |
| 249 | 250 | ||
| 250 | int cleanup_cndregister(cleanup *loc, fcallback cb, void *arg, unsigned char flag) { | 251 | int cleanup_cndregister(cleanup *loc, fcallback cb, void *arg, unsigned char flag) { |
| 251 | if(flag) | 252 | if(flag) return 0; |
| 252 | return 0; | ||
| 253 | return cleanup_register(loc, cb, arg); | 253 | return cleanup_register(loc, cb, arg); |
| 254 | } | 254 | } |
| 255 | 255 | ||
| 256 | int cleanup_clear(cleanup *loc) { | 256 | int cleanup_clear(cleanup *loc) { |
| 257 | if(!loc) {errno = EINVAL; return -1;} | 257 | if(!loc) ERRRET(EINVAL, -1); |
| 258 | |||
| 259 | loc->used = 0; | 258 | loc->used = 0; |
| 260 | return 0; | 259 | return 0; |
| 261 | } | 260 | } |
| 262 | 261 | ||
| 263 | int cleanup_fire(cleanup *loc) { | 262 | int cleanup_fire(cleanup *loc) { |
| 264 | if(!loc) {errno = EINVAL; return -1;} | 263 | if(!loc) ERRRET(EINVAL, -1); |
| 265 | 264 | ||
| 266 | for(int i = (loc->used - 1); i >= 0; i--) { | 265 | for(int i = (loc->used - 1); i >= 0; i--) { |
| 267 | if(loc->callbacks[i] == NULL) { | 266 | if(loc->callbacks[i] == NULL) { |
diff --git a/src/shared.h b/src/shared.h index adaad4a..0b401fe 100644 --- a/src/shared.h +++ b/src/shared.h | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | typedef int (*gcallback)(void*); // Generic callback signature | 8 | typedef int (*gcallback)(void*); // Generic callback signature |
| 9 | typedef void (*fcallback)(void*); // free()-like callback signature | 9 | typedef void (*fcallback)(void*); // free()-like callback signature |
| 10 | 10 | ||
| 11 | #define RETURNWERR(errval, retval) do {\ | 11 | #define ERRRET(errval, retval) do {\ |
| 12 | errno = (errval);\ | 12 | errno = (errval);\ |
| 13 | return (retval);\ | 13 | return (retval);\ |
| 14 | } while (0) | 14 | } while (0) |
diff --git a/src/threadpool.c b/src/threadpool.c index c4d8a5c..bd52c75 100644 --- a/src/threadpool.c +++ b/src/threadpool.c | |||
| @@ -5,9 +5,37 @@ | |||
| 5 | #include <errno.h> | 5 | #include <errno.h> |
| 6 | #include <error.h> | 6 | #include <error.h> |
| 7 | 7 | ||
| 8 | typedef struct task { | ||
| 9 | gcallback callback; | ||
| 10 | fcallback freecb; | ||
| 11 | void *data; | ||
| 12 | } task; | ||
| 13 | |||
| 14 | typedef struct tqnode { | ||
| 15 | struct tqnode *next; | ||
| 16 | struct tqnode *prev; | ||
| 17 | task *task; | ||
| 18 | } tqnode; | ||
| 19 | |||
| 20 | typedef struct taskqueue { | ||
| 21 | tqnode *start; | ||
| 22 | tqnode *end; | ||
| 23 | unsigned int size; | ||
| 24 | } taskqueue; | ||
| 25 | |||
| 26 | typedef struct ctqueue { | ||
| 27 | mtx_t mutex; | ||
| 28 | cnd_t cond; | ||
| 29 | unsigned char canceled; | ||
| 30 | |||
| 31 | taskqueue *tq; | ||
| 32 | thrd_t *thrdarr; | ||
| 33 | int talen; | ||
| 34 | } ctqueue; | ||
| 35 | |||
| 8 | 36 | ||
| 9 | task * task_init(gcallback callback, fcallback freecb, void *data) { | 37 | task * task_init(gcallback callback, fcallback freecb, void *data) { |
| 10 | if(callback == NULL) {errno = EINVAL; return NULL;} | 38 | if(callback == NULL) ERRRET(EINVAL, NULL); |
| 11 | 39 | ||
| 12 | task *tsk = calloc(1, sizeof(*tsk)); | 40 | task *tsk = calloc(1, sizeof(*tsk)); |
| 13 | if(!tsk) | 41 | if(!tsk) |
| @@ -33,7 +61,7 @@ void task_free(void *tsk) { | |||
| 33 | } | 61 | } |
| 34 | 62 | ||
| 35 | int task_fire(task *tsk) { | 63 | int task_fire(task *tsk) { |
| 36 | if(!tsk) {errno = EINVAL; return -1;} | 64 | if(!tsk) ERRRET(EINVAL, -1); |
| 37 | return tsk->callback(tsk->data); | 65 | return tsk->callback(tsk->data); |
| 38 | } | 66 | } |
| 39 | 67 | ||
| @@ -46,7 +74,7 @@ int task_fired(task *tsk) { | |||
| 46 | 74 | ||
| 47 | 75 | ||
| 48 | tqnode * tqnode_init(tqnode *next, tqnode *prev, task *tsk) { | 76 | tqnode * tqnode_init(tqnode *next, tqnode *prev, task *tsk) { |
| 49 | if(!tsk) {errno = EINVAL; return NULL;} | 77 | if(!tsk) ERRRET(EINVAL, NULL); |
| 50 | tqnode *node = calloc(1, sizeof(*node)); | 78 | tqnode *node = calloc(1, sizeof(*node)); |
| 51 | if(!node) | 79 | if(!node) |
| 52 | return NULL; | 80 | return NULL; |
| @@ -98,7 +126,7 @@ void taskqueue_free(void *tq) { | |||
| 98 | } | 126 | } |
| 99 | 127 | ||
| 100 | int taskqueue_handlefirst(taskqueue *tq, task *tsk) { | 128 | int taskqueue_handlefirst(taskqueue *tq, task *tsk) { |
| 101 | if(!tq || !tsk) {errno = EINVAL; return -1;} | 129 | if(!tq || !tsk) ERRRET(EINVAL, -1); |
| 102 | if(tq->size) {return 0;} | 130 | if(tq->size) {return 0;} |
| 103 | 131 | ||
| 104 | tqnode *first = tqnode_init(NULL, NULL, tsk); | 132 | tqnode *first = tqnode_init(NULL, NULL, tsk); |
| @@ -113,7 +141,7 @@ int taskqueue_handlefirst(taskqueue *tq, task *tsk) { | |||
| 113 | } | 141 | } |
| 114 | 142 | ||
| 115 | int taskqueue_push(taskqueue *tq, task *tsk) { | 143 | int taskqueue_push(taskqueue *tq, task *tsk) { |
| 116 | if(!tq || !tsk) {errno = EINVAL; return -1;} | 144 | if(!tq || !tsk) ERRRET(EINVAL, -1); |
| 117 | 145 | ||
| 118 | int hf; | 146 | int hf; |
| 119 | if((hf = taskqueue_handlefirst(tq, tsk))) | 147 | if((hf = taskqueue_handlefirst(tq, tsk))) |
| @@ -130,8 +158,8 @@ int taskqueue_push(taskqueue *tq, task *tsk) { | |||
| 130 | } | 158 | } |
| 131 | 159 | ||
| 132 | task * taskqueue_pop(taskqueue *tq) { | 160 | task * taskqueue_pop(taskqueue *tq) { |
| 133 | if(!tq) {errno = EINVAL; return NULL;} | 161 | if(!tq) ERRRET(EINVAL, NULL); |
| 134 | if(tq->size <= 0) {errno = ENODATA; return NULL;} | 162 | if(tq->size <= 0) ERRRET(ENODATA, NULL); |
| 135 | 163 | ||
| 136 | tqnode *end = tq->end; | 164 | tqnode *end = tq->end; |
| 137 | task *ret = end->task; | 165 | task *ret = end->task; |
| @@ -150,7 +178,7 @@ task * taskqueue_pop(taskqueue *tq) { | |||
| 150 | } | 178 | } |
| 151 | 179 | ||
| 152 | int taskqueue_pushfront(taskqueue *tq, task *tsk) { | 180 | int taskqueue_pushfront(taskqueue *tq, task *tsk) { |
| 153 | if(!tq || !tsk) {errno = EINVAL; return -1;} | 181 | if(!tq || !tsk) ERRRET(EINVAL, -1); |
| 154 | 182 | ||
| 155 | int hf; | 183 | int hf; |
| 156 | if((hf = taskqueue_handlefirst(tq, tsk))) | 184 | if((hf = taskqueue_handlefirst(tq, tsk))) |
| @@ -167,8 +195,8 @@ int taskqueue_pushfront(taskqueue *tq, task *tsk) { | |||
| 167 | } | 195 | } |
| 168 | 196 | ||
| 169 | task * taskqueue_popback(taskqueue *tq) { | 197 | task * taskqueue_popback(taskqueue *tq) { |
| 170 | if(!tq) {errno = EINVAL; return NULL;} | 198 | if(!tq) ERRRET(EINVAL, NULL); |
| 171 | if(tq->size <= 0) {errno = ENODATA; return NULL;} | 199 | if(tq->size <= 0) ERRRET(ENODATA, NULL); |
| 172 | 200 | ||
| 173 | tqnode *start = tq->start; | 201 | tqnode *start = tq->start; |
| 174 | task *ret = start->task; | 202 | task *ret = start->task; |
| @@ -187,7 +215,7 @@ task * taskqueue_popback(taskqueue *tq) { | |||
| 187 | } | 215 | } |
| 188 | 216 | ||
| 189 | int taskqueue_size(taskqueue *tq) { | 217 | int taskqueue_size(taskqueue *tq) { |
| 190 | if(!tq) {errno = EINVAL; return -1;} | 218 | if(!tq) ERRRET(EINVAL, -1); |
| 191 | return tq->size; | 219 | return tq->size; |
| 192 | } | 220 | } |
| 193 | 221 | ||
| @@ -219,7 +247,7 @@ static void ___ucl_cnddestroy(void *cond) { | |||
| 219 | } | 247 | } |
| 220 | 248 | ||
| 221 | ctqueue * ctqueue_init(int nthreads) { | 249 | ctqueue * ctqueue_init(int nthreads) { |
| 222 | if(nthreads <= 0) {errno = EINVAL; return NULL;} | 250 | if(nthreads <= 0) ERRRET(EINVAL, NULL); |
| 223 | cleanup_CREATE(6); | 251 | cleanup_CREATE(6); |
| 224 | 252 | ||
| 225 | ctqueue *ctq = calloc(1, sizeof(*ctq)); | 253 | ctqueue *ctq = calloc(1, sizeof(*ctq)); |
| @@ -264,7 +292,7 @@ ctqueue * ctqueue_init(int nthreads) { | |||
| 264 | } | 292 | } |
| 265 | 293 | ||
| 266 | int ctqueue_cancel(ctqueue *ctq) { | 294 | int ctqueue_cancel(ctqueue *ctq) { |
| 267 | if(!ctq) {errno = EINVAL; return -1;} | 295 | if(!ctq) ERRRET(EINVAL, -1); |
| 268 | 296 | ||
| 269 | __CTQ_INLOCK(ctq, 1, | 297 | __CTQ_INLOCK(ctq, 1, |
| 270 | ctq->canceled = 1; | 298 | ctq->canceled = 1; |
| @@ -297,7 +325,7 @@ void ctqueue_free(void *ctq) { | |||
| 297 | } | 325 | } |
| 298 | 326 | ||
| 299 | int ctqueue_waitpush(ctqueue *ctq, task *tsk) { | 327 | int ctqueue_waitpush(ctqueue *ctq, task *tsk) { |
| 300 | if(!ctq || !tsk) {errno = EINVAL; return -1;} | 328 | if(!ctq || !tsk) ERRRET(EINVAL, -1); |
| 301 | int retval = 0; | 329 | int retval = 0; |
| 302 | 330 | ||
| 303 | __CTQ_INLOCK(ctq, -1, | 331 | __CTQ_INLOCK(ctq, -1, |
| @@ -310,7 +338,7 @@ int ctqueue_waitpush(ctqueue *ctq, task *tsk) { | |||
| 310 | } | 338 | } |
| 311 | 339 | ||
| 312 | task * ctqueue_waitpop(ctqueue *ctq) { | 340 | task * ctqueue_waitpop(ctqueue *ctq) { |
| 313 | if(!ctq) {errno = EINVAL; return NULL;} | 341 | if(!ctq) ERRRET(EINVAL, NULL); |
| 314 | task *retval = NULL; | 342 | task *retval = NULL; |
| 315 | 343 | ||
| 316 | __CTQ_INLOCK(ctq, NULL, | 344 | __CTQ_INLOCK(ctq, NULL, |
| @@ -318,9 +346,8 @@ task * ctqueue_waitpop(ctqueue *ctq) { | |||
| 318 | cnd_wait(&ctq->cond, &ctq->mutex); | 346 | cnd_wait(&ctq->cond, &ctq->mutex); |
| 319 | 347 | ||
| 320 | if(ctq->canceled) { | 348 | if(ctq->canceled) { |
| 321 | errno = ECANCELED; | ||
| 322 | mtx_unlock(&ctq->mutex); | 349 | mtx_unlock(&ctq->mutex); |
| 323 | return NULL; | 350 | ERRRET(ECANCELED, NULL); |
| 324 | } | 351 | } |
| 325 | 352 | ||
| 326 | retval = taskqueue_pop(ctq->tq); | 353 | retval = taskqueue_pop(ctq->tq); |
| @@ -346,7 +373,7 @@ static int __CTQ_CONSUMER(void *ctq) { | |||
| 346 | } | 373 | } |
| 347 | 374 | ||
| 348 | int ctqueue_start(ctqueue *ctq) { | 375 | int ctqueue_start(ctqueue *ctq) { |
| 349 | if(!ctq) {errno = EINVAL; return -1;} | 376 | if(!ctq) ERRRET(EINVAL, -1); |
| 350 | 377 | ||
| 351 | ctq->canceled = 0; | 378 | ctq->canceled = 0; |
| 352 | 379 | ||
diff --git a/src/threadpool.h b/src/threadpool.h index 3048eea..7fda6f5 100644 --- a/src/threadpool.h +++ b/src/threadpool.h | |||
| @@ -4,33 +4,9 @@ | |||
| 4 | #include "shared.h" | 4 | #include "shared.h" |
| 5 | #include <threads.h> | 5 | #include <threads.h> |
| 6 | 6 | ||
| 7 | typedef struct task { | 7 | typedef struct task task; |
| 8 | gcallback callback; | 8 | typedef struct taskqueue taskqueue; |
| 9 | fcallback freecb; | 9 | typedef struct ctqueue ctqueue; |
| 10 | void *data; | ||
| 11 | } task; | ||
| 12 | |||
| 13 | typedef struct tqnode { | ||
| 14 | struct tqnode *next; | ||
| 15 | struct tqnode *prev; | ||
| 16 | task *task; | ||
| 17 | } tqnode; | ||
| 18 | |||
| 19 | typedef struct taskqueue { | ||
| 20 | tqnode *start; | ||
| 21 | tqnode *end; | ||
| 22 | unsigned int size; | ||
| 23 | } taskqueue; | ||
| 24 | |||
| 25 | typedef struct ctqueue { | ||
| 26 | mtx_t mutex; | ||
| 27 | cnd_t cond; | ||
| 28 | unsigned char canceled; | ||
| 29 | |||
| 30 | taskqueue *tq; | ||
| 31 | thrd_t *thrdarr; | ||
| 32 | int talen; | ||
| 33 | } ctqueue; | ||
| 34 | 10 | ||
| 35 | // Create a new task. Sets `errno` and returns `NULL` on error | 11 | // Create a new task. Sets `errno` and returns `NULL` on error |
| 36 | task * task_init(gcallback callback, fcallback freecb, void *data); | 12 | task * task_init(gcallback callback, fcallback freecb, void *data); |
