diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/build.c | 69 | ||||
-rw-r--r-- | src/evanix.c | 24 | ||||
-rw-r--r-- | src/meson.build | 1 | ||||
-rw-r--r-- | src/queue.c | 52 |
4 files changed, 140 insertions, 6 deletions
diff --git a/src/build.c b/src/build.c new file mode 100644 index 0000000..d846217 --- /dev/null +++ b/src/build.c @@ -0,0 +1,69 @@ +#include <errno.h> +#include <stdbool.h> +#include <pthread.h> +#include <stdlib.h> +#include <string.h> + +#include "build.h" +#include "queue.h" +#include "jobs.h" +#include "util.h" + +static int build(struct queue *queue); + +void *build_thread_entry(void *build_thread) +{ + struct build_thread *bt = build_thread; + int ret = 0; + + while (true) { + ret = sem_wait(&bt->queue->sem); + if (ret < 0) { + print_err("%s", strerror(errno)); + goto out; + } + + if (CIRCLEQ_EMPTY(&bt->queue->jobs)) { + if (bt->queue->state == Q_ITS_OVER) + goto out; + else if (bt->queue->state == Q_SEM_WAIT) + continue; + } + + ret = build(bt->queue); + if (ret < 0) + goto out; + } + +out: + pthread_exit(NULL); +} + +static int build(struct queue *queue) { + struct job *job; + int ret = 0; + + ret = queue_pop(queue, &job); + if (ret < 0) + return ret; + + printf("nix build %s^*\n", job->drv_path); + job_free(job); + + return 0; +} + +int build_thread_new(struct build_thread **build_thread, struct queue *q) +{ + struct build_thread *bt = NULL; + + bt = malloc(sizeof(*bt)); + if (bt == NULL) { + print_err("%s", strerror(errno)); + return -errno; + } + bt->queue = q; + + *build_thread = bt; + return 0; +} diff --git a/src/evanix.c b/src/evanix.c index dcac070..e83d0ea 100644 --- a/src/evanix.c +++ b/src/evanix.c @@ -1,12 +1,14 @@ #include <stdlib.h> #include <string.h> +#include "build.h" #include "queue.h" #include "util.h" int main(void) { struct queue_thread *queue_thread = NULL; + struct build_thread *build_thread = NULL; FILE *stream = NULL; int ret = 0; @@ -20,22 +22,40 @@ int main(void) goto out_free; } + ret = build_thread_new(&build_thread, queue_thread->queue); + if (ret < 0) { + free(stream); + goto out_free; + } + ret = pthread_create(&queue_thread->tid, NULL, queue_thread_entry, queue_thread); if (ret < 0) { print_err("%s", strerror(ret)); - ret = -ret; + goto out_free; + } + + ret = pthread_create(&build_thread->tid, NULL, build_thread_entry, + build_thread); + if (ret < 0) { + print_err("%s", strerror(ret)); goto out_free; } ret = pthread_join(queue_thread->tid, NULL); if (ret < 0) { print_err("%s", strerror(ret)); - ret = -ret; + goto out_free; + } + + ret = pthread_join(build_thread->tid, NULL); + if (ret < 0) { + print_err("%s", strerror(ret)); goto out_free; } out_free: queue_thread_free(queue_thread); + free(build_thread); exit(ret < 0 ? EXIT_FAILURE : EXIT_SUCCESS); } diff --git a/src/meson.build b/src/meson.build index bb68e18..41b31da 100644 --- a/src/meson.build +++ b/src/meson.build @@ -5,6 +5,7 @@ e = executable( 'jobs.c', 'util.c', 'queue.c', + 'build.c', ], include_directories: evanix_inc, diff --git a/src/queue.c b/src/queue.c index 6bf9092..746750e 100644 --- a/src/queue.c +++ b/src/queue.c @@ -8,6 +8,8 @@ #include "queue.h" #include "util.h" +static void queue_push(struct queue *queue, struct job *job); + void *queue_thread_entry(void *queue_thread) { struct queue_thread *qt = queue_thread; @@ -17,23 +19,51 @@ void *queue_thread_entry(void *queue_thread) while (true) { ret = job_read(qt->stream, &job); if (ret == -EOF) { + qt->queue->state = Q_ITS_OVER; + sem_post(&qt->queue->sem); + ret = 0; break; } else if (ret < 0) { break; } - pthread_mutex_lock(&qt->queue->mutex); - CIRCLEQ_INSERT_TAIL(&qt->queue->jobs, job, clist); - pthread_mutex_unlock(&qt->queue->mutex); + queue_push(qt->queue, job); } pthread_exit(NULL); } +int queue_pop(struct queue *queue, struct job **job) +{ + struct job *j = CIRCLEQ_FIRST(&queue->jobs); + + if (CIRCLEQ_EMPTY(&queue->jobs)) { + print_err("%s", "Empty queue"); + return -EPERM; + } + + pthread_mutex_lock(&queue->mutex); + CIRCLEQ_REMOVE(&queue->jobs, j, clist); + pthread_mutex_unlock(&queue->mutex); + + *job = j; + return 0; +} + +static void queue_push(struct queue *queue, struct job *job) +{ + pthread_mutex_lock(&queue->mutex); + CIRCLEQ_INSERT_TAIL(&queue->jobs, job, clist); + pthread_mutex_unlock(&queue->mutex); + + sem_post(&queue->sem); +} + void queue_thread_free(struct queue_thread *queue_thread) { struct job *job; + int ret; if (queue_thread == NULL) return; @@ -43,6 +73,13 @@ void queue_thread_free(struct queue_thread *queue_thread) free(job); } + ret = sem_destroy(&queue_thread->queue->sem); + if (ret < 0) + print_err("%s", strerror(errno)); + ret = pthread_mutex_destroy(&queue_thread->queue->mutex); + if (ret < 0) + print_err("%s", strerror(errno)); + free(queue_thread->queue); fclose(queue_thread->stream); } @@ -57,7 +94,6 @@ int queue_thread_new(struct queue_thread **queue_thread, FILE *stream) print_err("%s", strerror(errno)); return -errno; } - qt->stream = stream; qt->queue = malloc(sizeof(*qt->queue)); @@ -66,6 +102,14 @@ int queue_thread_new(struct queue_thread **queue_thread, FILE *stream) ret = -errno; goto out_free; } + qt->queue->state = Q_SEM_WAIT; + ret = sem_init(&qt->queue->sem, 0, 0); + if (ret < 0) { + print_err("%s", strerror(errno)); + ret = -errno; + goto out_free; + } + CIRCLEQ_INIT(&qt->queue->jobs); pthread_mutex_init(&qt->queue->mutex, NULL); |