/* $Id: schedbuf.c,v 1.8 2004/04/03 04:17:37 jmuelmen Exp $ */ #include "scheduler.h" #include "buf.h" #include "parse.h" #include "shell.h" #include "act.h" #include #include #include #include #include static buf_t _schedbuf; inline void schedbuf_init () { buf_init(&_schedbuf); } void schedbuf_lock () { pthread_mutex_lock(&_schedbuf.mut); } void schedbuf_unlock () { pthread_mutex_unlock(&_schedbuf.mut); } int schedbuf_buf (parse_action_t *a) { int retval; retval = buf_buf(&_schedbuf, a); return retval; } inline void schedbuf_dump () { printf("Sched buffer:\n"); buf_dump(&_schedbuf); } int schedbuf_process_segment (parse_action_t ***start, parse_action_t *end) { return buf_process_segment(&_schedbuf, start, end, 0); } void *schedbuf_process_action (void *p) /* run the statement pointed to by p */ { while (1) { parse_action_t **i = (parse_action_t **)p; /* remember where we are */ parse_action_t *a = *i; value_t *v; /* figure out what time it is */ time_t run; struct timeval tv_then; gettimeofday(&tv_then, NULL); /* lock the action */ pthread_mutex_lock(&a->statement.statement.mut); /* process the predicate */ ++i; schedbuf_process_segment(&i, a->statement.statement.eop); v = a->args[0]; /* wait until the predicate has been evaluated */ pthread_mutex_lock(&v->mut); while (!v->returned) { #ifdef WINDOWS_IS_DOGSHIT if (usleep(WINDOWS_IS_DOGSHIT)) perror("Sleeping on schedbuf argument eval"); #endif pthread_cond_wait(&v->has_returned, &v->mut); } /* figure out when we're next supposed to run */ conv_time(&run, v); pthread_mutex_unlock(&v->mut); /* check that we haven't been canceled */ if (a->statement.statement.cancel) return NULL; /* process the statement */ ++i; schedbuf_process_segment(&i, a->statement.statement.eos); /* sleep for the right amount of time */ pthread_mutex_unlock(&a->statement.statement.mut); if (buf_sleep(run, 0, &tv_then) == -1) perror("Sleeping"); } return NULL; } int schedbuf_process () { static parse_action_t **i = _schedbuf.actions; for (; i < _schedbuf.actions + _schedbuf.n_actions; ++i) { pthread_t thr; parse_action_t *a = *i; /* run a thread that waits for this action's time to come */ pthread_create(&thr, NULL, schedbuf_process_action, i); while (*i != a->statement.statement.eos) ++i; } return 0; } void *schedbuf (void *arg) { while (1) { schedbuf_lock(); /* wait for the buffer to change */ while (!_schedbuf.changed) { #ifdef WINDOWS_IS_DOGSHIT if (usleep(WINDOWS_IS_DOGSHIT)) perror("Sleeping on schedbuf change"); #endif /* printf("Waiting on schedbuf contents\n"); */ pthread_cond_wait(&_schedbuf.has_changed, &_schedbuf.mut); } _schedbuf.changed = 0; /* when it's changed, process it */ schedbuf_process(); schedbuf_unlock(); } return NULL; } void schedbuf_cancel (int j) { int i; parse_action_t **a = _schedbuf.actions; schedbuf_lock(); for (i = 0; i != j ; ++i) { while (++a < _schedbuf.actions + _schedbuf.n_actions && (*a)->type != sched_s); if (a >= _schedbuf.actions + _schedbuf.n_actions) break; } if (i != j) return; if ((*a)->type != sched_s) printf("Uh oh, not a scheduling statement."); pthread_mutex_lock(&(*a)->statement.statement.mut); (*a)->statement.statement.cancel = 1; pthread_mutex_unlock(&(*a)->statement.statement.mut); schedbuf_unlock(); }