static int pipe_read(struct fnode *f, void *buf, unsigned int len) { struct pipe_priv *pp; int out, len_available; uint8_t *ptr = buf; if (f->owner != &mod_pipe) return -EINVAL; pp = (struct pipe_priv *)f->priv; if (!pp) return -EINVAL; if (pp->fno_r != f) return -EPERM; len_available = cirbuf_bytesinuse(pp->cb); if (len_available <= 0) { pp->pid_r = scheduler_get_cur_pid(); task_suspend(); return SYS_CALL_AGAIN; } for(out = 0; out < len; out++) { /* read data */ if (cirbuf_readbyte(pp->cb, ptr) != 0) break; ptr++; } pp->pid_r = 0; return out; }
static int pipe_close(struct fnode *f) { struct pipe_priv *pp; uint16_t pid; pid = scheduler_get_cur_pid(); if (!f) return -EINVAL; if (f->owner != &mod_pipe) return -EINVAL; pp = (struct pipe_priv *)f->priv; if (!pp) return -EINVAL; if ((f == pp->fno_r) && (f->usage == 1)) { pp->fno_r = NULL; fno_unlink(f); if ((pp->pid_w != pid) && (pp->pid_w > 0)) { task_resume(pp->pid_w); } } if ((f == pp->fno_w) && (f->usage == 1)) { pp->fno_w = NULL; fno_unlink(f); if ((pp->pid_r != pid) && (pp->pid_r > 0)) { task_resume(pp->pid_r); } } if ((!pp->fno_w) && (!pp->fno_r)) kfree(pp); return 0; }
static void _del_listener(sem_t *s) { int i; int pid = scheduler_get_cur_pid(); for (i = 0; i < s->listeners; i++) { if (s->listener[i] == pid) { s->listener[i] = -1; return; } } }
/* Semaphore: internal functions */ static void _add_listener(sem_t *s) { int i; int pid = scheduler_get_cur_pid(); for (i = 0; i < s->listeners; i++) { if (s->listener[i] == pid) return; } s->listener = krealloc(s->listener, sizeof(int) * (s->listeners + 1)); if (!s->listener) return; s->listener[s->listeners++] = pid; }
static int pipe_write(struct fnode *f, const void *buf, unsigned int len) { struct pipe_priv *pp; int out, len_available; const uint8_t *ptr = buf; if (f->owner != &mod_pipe) return -EINVAL; pp = (struct pipe_priv *)f->priv; if (!pp) return -EINVAL; if (pp->fno_w != f) return -EPERM; out = pp->w_off; len_available = cirbuf_bytesfree(pp->cb); if (len_available > (len - out)) len_available = (len - out); for(; out < len_available; out++) { /* write data */ if (cirbuf_writebyte(pp->cb, *(ptr + out)) != 0) break; } if (out < len) { pp->pid_w = scheduler_get_cur_pid(); pp->w_off = out; task_suspend(); return SYS_CALL_AGAIN; } pp->w_off = 0; pp->pid_w = 0; return out; }