// Grab a lock on the FIFO. Then do a condwait until we get a message. // status_t message_get(tid_t *sender, msgid_t *msg, msgarg_t *arg1, msgarg_t *arg2) { struct message *pm; task p = self(); // First lock the queue to see if there's a message available. if (!fifo_lock(p->q)) return false; if (fifo_nelem(p->q) == 0) { if (!fifo_unlock(p->q)) return false; if (!fifo_wait_cond(p->q)) return false; } // We now hold a lock. assert(fifo_nelem(p->q) > 0); if ((pm = fifo_get(p->q)) == NULL) die("%s(): Internal error\n", __func__); *sender = pm->sender; *msg = pm->msg; *arg1 = pm->arg1; *arg2 = pm->arg2; fifo_unlock(p->q); free(pm); return success; }
static int stream_load_loopL(lua_State *L) { int fd; ssize_t n, len; char *filename; /* * 1: self * 2: file */ filename = alloca(PATH_MAX); if (!squeezeplay_find_file(lua_tostring(L, 2), filename)) { LOG_ERROR(log_audio_decode, "Can't find image %s\n", lua_tostring(L, 2)); return 0; } if ((fd = open(filename, O_RDONLY)) < 0) { LOG_ERROR(log_audio_decode, "Can't open %s", lua_tostring(L, 2)); return 0; } fifo_lock(&streambuf_fifo); streambuf_lptr = streambuf_fifo.wptr; streambuf_loop = TRUE; n = fifo_bytes_free(&streambuf_fifo); if ((len = read(fd, streambuf_buf + streambuf_fifo.wptr, n)) < 0) { goto read_err; } fifo_wptr_incby(&streambuf_fifo, len); n = fifo_bytes_free(&streambuf_fifo); if (n) { if ((n = read(fd, streambuf_buf + streambuf_fifo.wptr, n)) < 0) { goto read_err; } fifo_wptr_incby(&streambuf_fifo, n); len += n; } streambuf_streaming = FALSE; streambuf_bytes_received = len; streambuf_filter = streambuf_next_filter; streambuf_next_filter = NULL; fifo_unlock(&streambuf_fifo); close(fd); return 0; read_err: fifo_unlock(&streambuf_fifo); close(fd); return 0; }
size_t maru_fifo_write_avail(maru_fifo *fifo) { fifo_lock(fifo); size_t ret = maru_fifo_write_avail_nolock(fifo); fifo_unlock(fifo); return ret; }
maru_error maru_fifo_read_lock(maru_fifo *fifo, size_t size, struct maru_fifo_locked_region *region) { fifo_lock(fifo); size_t avail_first = fifo->buffer_size - fifo->read_lock_end; size_t read_first = size; if (read_first > avail_first) read_first = avail_first; size_t read_second = size - read_first; region->first = fifo->buffer + fifo->read_lock_end; region->first_size = read_first; region->second = read_second ? fifo->buffer : NULL; region->second_size = read_second; if (region->second_size) fifo->read_lock_end = region->second_size; else fifo->read_lock_end = (fifo->read_lock_end + region->first_size) & fifo->buffer_mask; fifo_unlock(fifo); return LIBMARU_SUCCESS; }
/* read bytes from the streaming socket and discard - used by network test to measure network throughput*/ static int stream_readtonullL(lua_State *L) { struct stream *stream; char buf[4094]; int n; /* * 1: Stream (self) */ stream = lua_touserdata(L, 1); n = recv(stream->fd, buf, sizeof(buf), 0); if (n > 0) { fifo_lock(&streambuf_fifo); streambuf_bytes_received += n; fifo_unlock(&streambuf_fifo); lua_pushinteger(L, n); return 1; } else if (n == -1 && errno == EAGAIN) { lua_pushinteger(L, 0); return 1; } else { CLOSESOCKET(stream->fd); lua_pushnil(L); lua_pushstring(L, strerror(n)); return 2; } }
maru_error maru_fifo_read_unlock(maru_fifo *fifo, const struct maru_fifo_locked_region *region) { maru_error ret = LIBMARU_SUCCESS; fifo_lock(fifo); // Check if ordering of unlocks differ from order of locks. if (fifo->buffer + fifo->read_lock_begin != region->first) { ret = LIBMARU_ERROR_INVALID; goto end; } size_t new_begin = (fifo->read_lock_begin + region->first_size) & fifo->buffer_mask; if (region->second_size && new_begin != 0) { ret = LIBMARU_ERROR_INVALID; goto end; } new_begin += region->second_size; fifo->read_lock_begin = new_begin; if (maru_fifo_write_avail_nolock(fifo) >= fifo->write_trigger && fifo->write_fd >= 0) eventfd_write(fifo->write_fd, 1); end: fifo_unlock(fifo); return ret; }
void streambuf_set_filter(streambuf_filter_t filter) { fifo_lock(&streambuf_fifo); streambuf_next_filter = filter; fifo_unlock(&streambuf_fifo); }
static unsigned char read_byte(void) { unsigned char has_read = 0; unsigned char c = 0; while (!has_read) { int_wait(); fifo_lock(&gfifo); if (gfifo.size) { c = fifo_pop(&gfifo); has_read = 1; } else if (gfifo.error) { has_read = 1; } fifo_unlock(&gfifo); } return c; }
static void streambuf_feedL(u8_t *buf, size_t size, lua_State *L) { size_t n; fifo_lock(&streambuf_fifo); streambuf_streaming = TRUE; streambuf_bytes_received += size; while (size) { n = fifo_bytes_until_wptr_wrap(&streambuf_fifo); if (n > size) { n = size; } memcpy(streambuf_buf + streambuf_fifo.wptr, buf, n); proxy_chunk(streambuf_buf + streambuf_fifo.wptr, n, L); fifo_wptr_incby(&streambuf_fifo, n); buf += n; size -= n; } fifo_unlock(&streambuf_fifo); }
void maru_fifo_kill_notification(maru_fifo *fifo) { fifo_lock(fifo); fifo->dead = true; eventfd_write(fifo->write_fd, 1); eventfd_write(fifo->read_fd, 1); fifo_unlock(fifo); }
void streambuf_flush(void) { fifo_lock(&streambuf_fifo); streambuf_fifo.rptr = 0; streambuf_fifo.wptr = 0; fifo_unlock(&streambuf_fifo); }
maru_error maru_fifo_write_notify_ack(maru_fifo *fifo) { fifo_lock(fifo); maru_error ret = fifo->dead ? LIBMARU_ERROR_DEAD : LIBMARU_SUCCESS; if (!fifo->dead) maru_fifo_write_notify_ack_nolock(fifo); fifo_unlock(fifo); return ret; }
static int stream_mark_loopL(lua_State *L) { fifo_lock(&streambuf_fifo); streambuf_loop = TRUE; fifo_unlock(&streambuf_fifo); return 0; }
status_t fifo_write_signal(fifo p, void *data) { status_t rc; assert(p != NULL); assert(data != NULL); if (!fifo_lock(p)) return failure; if (!fifo_add(p, data)) { fifo_unlock(p); return failure; } rc = fifo_signal(p); fifo_unlock(p); return rc; }
size_t streambuf_get_freebytes(void) { size_t n; fifo_lock(&streambuf_fifo); n = fifo_bytes_free(&streambuf_fifo); fifo_unlock(&streambuf_fifo); return n; }
void streambuf_get_status(size_t *size, size_t *usedbytes, u32_t *bytesL, u32_t *bytesH) { fifo_lock(&streambuf_fifo); *size = STREAMBUF_SIZE; *usedbytes = fifo_bytes_used(&streambuf_fifo); *bytesL = streambuf_bytes_received & 0xFFFFFFFF; *bytesH = streambuf_bytes_received >> 32; fifo_unlock(&streambuf_fifo); }
size_t streambuf_get_usedbytes(void) { size_t n; fifo_lock(&streambuf_fifo); n = fifo_bytes_used(&streambuf_fifo); fifo_unlock(&streambuf_fifo); return n; }
status_t fifo_wait_cond(fifo p) { assert(p != NULL); if (!fifo_lock(p)) return failure; if (!wlock_wait(p->lock)) { fifo_unlock(p); return failure; } /* OK, we have the lock. See if there are data or not. * No data means that fifo_wake() was called. */ if (fifo_nelem(p) == 0) { fifo_unlock(p); return fail(ENOENT); } return success; }
ssize_t streambuf_feed_fd(int fd, lua_State *L) { ssize_t n, size; fifo_lock(&streambuf_fifo); streambuf_streaming = TRUE; size = fifo_bytes_free(&streambuf_fifo); if (size < 4096) { fifo_unlock(&streambuf_fifo); return -ENOSPC; /* no space */ } n = fifo_bytes_until_wptr_wrap(&streambuf_fifo); if (n > size) { n = size; } n = recv(fd, streambuf_buf + streambuf_fifo.wptr, n, 0); if (n < 0) { streambuf_streaming = FALSE; fifo_unlock(&streambuf_fifo); return -SOCKETERROR; } else if (n == 0) { streambuf_streaming = FALSE; } else { proxy_chunk(streambuf_buf + streambuf_fifo.wptr, n, L); fifo_wptr_incby(&streambuf_fifo, n); streambuf_bytes_received += n; } fifo_unlock(&streambuf_fifo); return n; }
/* returns true if the stream is still open but cannot yet supply the requested bytes */ bool_t streambuf_would_wait_for(size_t bytes) { size_t n; if (!streambuf_streaming) { return FALSE; } fifo_lock(&streambuf_fifo); n = fifo_bytes_used(&streambuf_fifo); fifo_unlock(&streambuf_fifo); return n < bytes; }
int serial_pop_fifo(unsigned char* c) { int res = -1; fifo_lock(&gfifo); if (gfifo.size) { *c = fifo_pop(&gfifo); res = 0; } fifo_unlock(&gfifo); return res; }
static int stream_icy_metaintervalL(lua_State *L) { /* * 1: Stream (self) * 2: meta interval */ fifo_lock(&streambuf_fifo); streambuf_filter = streambuf_icy_filter; icy_meta_interval = lua_tointeger(L, 2); icy_meta_remaining = icy_meta_interval; fifo_unlock(&streambuf_fifo); return 0; }
static void *reader(void *arg) { fifo f = arg; while (fifo_wait_cond(f)) { char *s; while ((s = fifo_get(f)) != NULL) { fprintf(stderr, "From reader, who read: %s\n", s); free(s); } if (!fifo_unlock(f)) break; } fprintf(stderr, "Exiting %s...\n", __func__); return NULL; }
maru_error maru_fifo_set_read_trigger(maru_fifo *fifo, size_t size) { maru_error ret = LIBMARU_SUCCESS; fifo_lock(fifo); if (size == 0) size = 1; if (size + fifo->write_trigger >= fifo->buffer_size) { ret = LIBMARU_ERROR_INVALID; goto end; } fifo->read_trigger = size; end: fifo_unlock(fifo); return ret; }
size_t streambuf_read(u8_t *buf, size_t min, size_t max, bool_t *streaming) { ssize_t n; fifo_lock(&streambuf_fifo); if (streambuf_filter) { /* filters are called with the streambuf locked */ n = streambuf_filter(buf, min, max, streaming); if (n < 0) { /* filter returned an error */ current_decoder_state |= DECODE_STATE_ERROR; n = 0; } } else { n = streambuf_fast_read(buf, min, max, streaming); } fifo_unlock(&streambuf_fifo); return n; }
void streambuf_filter_unlock(void) { fifo_unlock(&streambuf_fifo); }
static int stream_connectL(lua_State *L) { /* * 1: self * 2: server_ip * 3: server_port */ struct sockaddr_in serv_addr; struct stream *stream; int flags; int err; socket_t fd; /* Server address and port */ memset(&serv_addr, 0, sizeof(serv_addr)); if (lua_type(L, 2) == LUA_TSTRING) { serv_addr.sin_addr.s_addr = inet_addr(luaL_checkstring(L, 2)); } else { serv_addr.sin_addr.s_addr = htonl(luaL_checkinteger(L, 2)); } serv_addr.sin_port = htons(luaL_checkinteger(L, 3)); serv_addr.sin_family = AF_INET; LOG_DEBUG(log_audio_decode, "streambuf connect %s:%d", inet_ntoa(serv_addr.sin_addr), ntohs(serv_addr.sin_port)); /* Create socket */ fd = socket(AF_INET, SOCK_STREAM, 0); if (fd == INVALID_SOCKET) { lua_pushnil(L); lua_pushstring(L, strerror(SOCKETERROR)); return 2; } /* Make socket non-blocking */ #if defined(WIN32) { u_long iMode = 0; flags = ioctlsocket(fd, FIONBIO, &iMode); } #else flags = fcntl(fd, F_GETFL, 0); flags |= O_NONBLOCK; fcntl(fd, F_SETFL, flags); #endif /* Connect socket */ err = connect(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); if (err != 0 #if !defined(WIN32) && SOCKETERROR != EINPROGRESS #endif ) { CLOSESOCKET(fd); lua_pushnil(L); lua_pushstring(L, strerror(SOCKETERROR)); return 2; } /* Stream object */ stream = lua_newuserdata(L, sizeof(struct stream)); memset(stream, 0, sizeof(*stream)); stream->fd = fd; luaL_getmetatable(L, "squeezeplay.stream"); lua_setmetatable(L, -2); fifo_lock(&streambuf_fifo); streambuf_loop = FALSE; streambuf_bytes_received = 0; streambuf_copyright = FALSE; streambuf_filter = streambuf_next_filter; streambuf_next_filter = NULL; fifo_unlock(&streambuf_fifo); return 1; }