static int task_spawn_exec(FAR pid_t *pidp, FAR const char *name, main_t entry, FAR const posix_spawnattr_t *attr, FAR char * const *argv) { size_t stacksize; int priority; int pid; int ret = OK; /* Disable pre-emption so that we can modify the task parameters after * we start the new task; the new task will not actually begin execution * until we re-enable pre-emption. */ sched_lock(); /* Use the default task priority and stack size if no attributes are provided */ if (attr) { priority = attr->priority; stacksize = attr->stacksize; } else { struct sched_param param; /* Set the default priority to the same priority as this task */ ret = sched_getparam(0, ¶m); if (ret < 0) { goto errout; } priority = param.sched_priority; stacksize = CONFIG_TASK_SPAWN_DEFAULT_STACKSIZE; } /* Start the task */ pid = task_create(name, priority, stacksize, entry, argv); if (pid < 0) { ret = get_errno(); sdbg("ERROR: task_create failed: %d\n", ret); goto errout; } /* Return the task ID to the caller */ if (pid) { *pidp = pid; } /* Now set the attributes. Note that we ignore all of the return values * here because we have already successfully started the task. If we * return an error value, then we would also have to stop the task. */ if (attr) { (void)spawn_execattrs(pid, attr); } /* Re-enable pre-emption and return */ errout: sched_unlock(); return ret; }
/* this is just int because we must handle any positive value */ int status () { return get_errno(); }
int losetup(FAR const char *devname, FAR const char *filename, uint16_t sectsize, off_t offset, bool readonly) { FAR struct loop_struct_s *dev; struct stat sb; int ret; /* Sanity check */ #ifdef CONFIG_DEBUG if (!devname || !filename || !sectsize) { return -EINVAL; } #endif /* Get the size of the file */ ret = stat(filename, &sb); if (ret < 0) { dbg("Failed to stat %s: %d\n", filename, get_errno()); return -get_errno(); } /* Check if the file system is big enough for one block */ if (sb.st_size - offset < sectsize) { dbg("File is too small for blocksize\n"); return -ERANGE; } /* Allocate a loop device structure */ dev = (FAR struct loop_struct_s *)kmm_zalloc(sizeof(struct loop_struct_s)); if (!dev) { return -ENOMEM; } /* Initialize the loop device structure. */ sem_init(&dev->sem, 0, 1); dev->nsectors = (sb.st_size - offset) / sectsize; dev->sectsize = sectsize; dev->offset = offset; /* Open the file. */ #ifdef CONFIG_FS_WRITABLE dev->writeenabled = false; /* Assume failure */ dev->fd = -1; /* First try to open the device R/W access (unless we are asked * to open it readonly). */ if (!readonly) { dev->fd = open(filename, O_RDWR); } if (dev->fd >= 0) { dev->writeenabled = true; /* Success */ } else #endif { /* If that fails, then try to open the device read-only */ dev->fd = open(filename, O_RDWR); if (dev->fd < 0) { dbg("Failed to open %s: %d\n", filename, get_errno()); ret = -get_errno(); goto errout_with_dev; } } /* Inode private data will be reference to the loop device structure */ ret = register_blockdriver(devname, &g_bops, 0, dev); if (ret < 0) { fdbg("register_blockdriver failed: %d\n", -ret); goto errout_with_fd; } return OK; errout_with_fd: close(dev->fd); errout_with_dev: kmm_free(dev); return ret; }
static ssize_t _gnutls_stream_read (gnutls_session_t session, mbuffer_st **bufel, size_t size, gnutls_pull_func pull_func) { size_t left; ssize_t i = 0; size_t max_size = _gnutls_get_max_decrypted_data(session); char *ptr; gnutls_transport_ptr_t fd = session->internals.transport_recv_ptr; *bufel = _mbuffer_alloc (0, MAX(max_size, size)); if (!*bufel) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } ptr = (*bufel)->msg.data; session->internals.direction = 0; left = size; while (left > 0) { reset_errno (session); i = pull_func (fd, &ptr[size - left], left); if (i < 0) { int err = get_errno (session); _gnutls_read_log ("READ: %d returned from %p, errno=%d gerrno=%d\n", (int) i, fd, errno, session->internals.errnum); if (err == EAGAIN || err == EINTR) { if (size - left > 0) { _gnutls_read_log ("READ: returning %d bytes from %p\n", (int) (size - left), fd); goto finish; } if (err == EAGAIN) return GNUTLS_E_AGAIN; return GNUTLS_E_INTERRUPTED; } else { gnutls_assert (); return GNUTLS_E_PULL_ERROR; } } else { _gnutls_read_log ("READ: Got %d bytes from %p\n", (int) i, fd); if (i == 0) break; /* EOF */ } left -= i; (*bufel)->msg.size += i; } finish: _gnutls_read_log ("READ: read %d bytes from %p\n", (int) (size - left), fd); return (size - left); }
int pthread_cond_timedwait(FAR pthread_cond_t *cond, FAR pthread_mutex_t *mutex, FAR const struct timespec *abstime) { FAR struct tcb_s *rtcb = (FAR struct tcb_s *)g_readytorun.head; int ticks; int mypid = (int)getpid(); irqstate_t int_state; int ret = OK; int status; sdbg("cond=0x%p mutex=0x%p abstime=0x%p\n", cond, mutex, abstime); DEBUGASSERT(rtcb->waitdog == NULL); /* Make sure that non-NULL references were provided. */ if (!cond || !mutex) { ret = EINVAL; } /* Make sure that the caller holds the mutex */ else if (mutex->pid != mypid) { ret = EPERM; } /* If no wait time is provided, this function degenerates to * the same behavior as pthread_cond_wait(). */ else if (!abstime) { ret = pthread_cond_wait(cond, mutex); } else { /* Create a watchdog */ rtcb->waitdog = wd_create(); if (!rtcb->waitdog) { ret = EINVAL; } else { sdbg("Give up mutex...\n"); /* We must disable pre-emption and interrupts here so that * the time stays valid until the wait begins. This adds * complexity because we assure that interrupts and * pre-emption are re-enabled correctly. */ sched_lock(); int_state = irqsave(); /* Convert the timespec to clock ticks. We must disable pre-emption * here so that this time stays valid until the wait begins. */ ret = clock_abstime2ticks(CLOCK_REALTIME, abstime, &ticks); if (ret) { /* Restore interrupts (pre-emption will be enabled when * we fall through the if/then/else */ irqrestore(int_state); } else { /* Check the absolute time to wait. If it is now or in the past, then * just return with the timedout condition. */ if (ticks <= 0) { /* Restore interrupts and indicate that we have already timed out. * (pre-emption will be enabled when we fall through the * if/then/else */ irqrestore(int_state); ret = ETIMEDOUT; } else { /* Give up the mutex */ mutex->pid = 0; ret = pthread_givesemaphore((sem_t*)&mutex->sem); if (ret) { /* Restore interrupts (pre-emption will be enabled when * we fall through the if/then/else) */ irqrestore(int_state); } else { /* Start the watchdog */ wd_start(rtcb->waitdog, ticks, (wdentry_t)pthread_condtimedout, 2, (uint32_t)mypid, (uint32_t)SIGCONDTIMEDOUT); /* Take the condition semaphore. Do not restore interrupts * until we return from the wait. This is necessary to * make sure that the watchdog timer and the condition wait * are started atomically. */ status = sem_wait((sem_t*)&cond->sem); /* Did we get the condition semaphore. */ if (status != OK) { /* NO.. Handle the special case where the semaphore wait was * awakened by the receipt of a signal -- presumably the * signal posted by pthread_condtimedout(). */ if (get_errno() == EINTR) { sdbg("Timedout!\n"); ret = ETIMEDOUT; } else { ret = EINVAL; } } /* The interrupts stay disabled until after we sample the errno. * This is because when debug is enabled and the console is used * for debug output, then the errno can be altered by interrupt * handling! (bad) */ irqrestore(int_state); } /* Reacquire the mutex (retaining the ret). */ sdbg("Re-locking...\n"); status = pthread_takesemaphore((sem_t*)&mutex->sem); if (!status) { mutex->pid = mypid; } else if (!ret) { ret = status; } } /* Re-enable pre-emption (It is expected that interrupts * have already been re-enabled in the above logic) */ sched_unlock(); } /* We no longer need the watchdog */ wd_delete(rtcb->waitdog); rtcb->waitdog = NULL; } } sdbg("Returning %d\n", ret); return ret; }
int nanosleep(FAR const struct timespec *rqtp, FAR struct timespec *rmtp) { irqstate_t flags; systime_t starttick; sigset_t set; struct siginfo value; int errval; #ifdef CONFIG_DEBUG /* Warning avoidance */ int ret; #endif if (!rqtp || rqtp->tv_nsec < 0 || rqtp->tv_nsec >= 1000000000) { errval = EINVAL; goto errout; } /* Get the start time of the wait. Interrupts are disabled to prevent * timer interrupts while we do tick-related calculations before and * after the wait. */ flags = irqsave(); starttick = clock_systimer(); /* Set up for the sleep. Using the empty set means that we are not * waiting for any particular signal. However, any unmasked signal can * still awaken sigtimedwait(). */ (void)sigemptyset(&set); /* nanosleep is a simple application of sigtimedwait. */ #ifdef CONFIG_DEBUG /* Warning avoidance */ ret = sigtimedwait(&set, &value, rqtp); #else (void)sigtimedwait(&set, &value, rqtp); #endif /* sigtimedwait() cannot succeed. It should always return error with * either (1) EAGAIN meaning that the timeout occurred, or (2) EINTR * meaning that some other unblocked signal was caught. */ errval = get_errno(); DEBUGASSERT(ret < 0 && (errval == EAGAIN || errval == EINTR)); if (errval == EAGAIN) { /* The timeout "error" is the normal, successful result */ irqrestore(flags); return OK; } /* If we get there, the wait has failed because we were awakened by a * signal. Return the amount of "unwaited" time if rmtp is non-NULL. */ if (rmtp) { systime_t elapsed; systime_t remaining; int ticks; /* First get the number of clock ticks that we were requested to * wait. */ (void)clock_time2ticks(rqtp, &ticks); /* Get the number of ticks that we actually waited */ elapsed = clock_systimer() - starttick; /* The difference between the number of ticks that we were requested * to wait and the number of ticks that we actualy waited is that * amount of time that we failed to wait. */ if (elapsed >= (uint32_t)ticks) { remaining = 0; } else { remaining = (uint32_t)ticks - elapsed; } (void)clock_ticks2time((int)remaining, rmtp); } irqrestore(flags); errout: set_errno(errval); return ERROR; }
static FAR struct iob_s *iob_allocwait(bool throttled) { FAR struct iob_s *iob; irqstate_t flags; FAR sem_t *sem; int ret = OK; #if CONFIG_IOB_THROTTLE > 0 /* Select the semaphore count to check. */ sem = (throttled ? &g_throttle_sem : &g_iob_sem); #else sem = &g_iob_sem; #endif /* The following must be atomic; interrupt must be disabled so that there * is no conflict with interrupt level I/O buffer allocations. This is * not as bad as it sounds because interrupts will be re-enabled while * we are waiting for I/O buffers to become free. */ flags = irqsave(); do { /* Try to get an I/O buffer. If successful, the semaphore count * will be decremented atomically. */ iob = iob_tryalloc(throttled); if (!iob) { /* If not successful, then the semaphore count was less than or * equal to zero (meaning that there are no free buffers). We * need to wait for an I/O buffer to be released when the semaphore * count will be incremented. */ ret = sem_wait(sem); if (ret < 0) { int errcode = get_errno(); /* EINTR is not an error! EINTR simply means that we were * awakened by a signal and we should try again. * * REVISIT: Many end-user interfaces are required to return * with an error if EINTR is set. Most uses of this function * is in internal, non-user logic. But are there cases where * the error should be returned. */ if (errcode == EINTR) { /* Force a success indication so that we will continue * looping. */ ret = 0; } else { /* Stop the loop and return a error */ DEBUGASSERT(errcode > 0); ret = -errcode; } } else { /* When we wake up from wait successfully, an I/O buffer was * returned to the free list. However, if there are concurrent * allocations from interrupt handling, then I suspect that * there is a race condition. But no harm, we will just wait * again in that case. * * We need release our count so that it is available to * iob_tryalloc(), perhaps allowing another thread to take our * count. In that event, iob_tryalloc() will fail above and * we will have to wait again. * * TODO: Consider a design modification to permit us to * complete the allocation without losing our count. */ sem_post(sem); } } } while (ret == OK && iob == NULL); irqrestore(flags); return iob; }
long do_open(char * arg1, uint32_t arg2, uint32_t arg3) { /* XXX: don't let the %s stay in there */ DPRINTF("open(%s, 0x%x, 0x%x)\n", arg1, arg2, arg3); return get_errno(open(arg1, arg2, arg3)); }
/* ??? Implement proper locking for ioctls. */ static long do_ioctl(long fd, long cmd, long arg) { const IOCTLEntry *ie; const argtype *arg_type; int ret; uint8_t buf_temp[MAX_STRUCT_SIZE]; int target_size; void *argptr; ie = ioctl_entries; for(;;) { if (ie->target_cmd == 0) { gemu_log("Unsupported ioctl: cmd=0x%04lx\n", cmd); return -ENOSYS; } if (ie->target_cmd == cmd) break; ie++; } arg_type = ie->arg_type; #if defined(DEBUG) gemu_log("ioctl: cmd=0x%04lx (%s)\n", cmd, ie->name); #endif switch(arg_type[0]) { case TYPE_NULL: /* no argument */ ret = get_errno(ioctl(fd, ie->host_cmd)); break; case TYPE_PTRVOID: case TYPE_INT: /* int argment */ ret = get_errno(ioctl(fd, ie->host_cmd, arg)); break; case TYPE_PTR: arg_type++; target_size = thunk_type_size(arg_type, 0); switch(ie->access) { case IOC_R: ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp)); if (!is_error(ret)) { argptr = lock_user(arg, target_size, 0); thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET); unlock_user(argptr, arg, target_size); } break; case IOC_W: argptr = lock_user(arg, target_size, 1); thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST); unlock_user(argptr, arg, 0); ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp)); break; default: case IOC_RW: argptr = lock_user(arg, target_size, 1); thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST); unlock_user(argptr, arg, 0); ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp)); if (!is_error(ret)) { argptr = lock_user(arg, target_size, 0); thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET); unlock_user(argptr, arg, target_size); } break; } break; default: gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n", cmd, arg_type[0]); ret = -ENOSYS; break; } return ret; }
s32 setsockopt(s32 s, s32 level, s32 optname, vm::cptr<void> optval, u32 optlen) { libnet.warning("setsockopt(s=%d, level=%d, optname=%d, optval=*0x%x, optlen=%d)", s, level, optname, optval, optlen); std::shared_ptr<sys_net_socket> sock = idm::get<sys_net_socket>(s); if (!sock) { libnet.error("setsockopt(): socket does not exist"); return -1; } if (level != SOL_SOCKET && level != IPPROTO_TCP) { fmt::throw_exception("Invalid socket option level!" HERE); } s32 ret; #ifdef _WIN32 if (level == SOL_SOCKET) { switch (optname) { case OP_SO_NBIO: { unsigned long mode = *(unsigned long*)optval.get_ptr(); ret = ioctlsocket(sock->s, FIONBIO, &mode); break; } case OP_SO_SNDBUF: { u32 sendbuff = *(u32*)optval.get_ptr(); ret = ::setsockopt(sock->s, SOL_SOCKET, SO_SNDBUF, (const char*)&sendbuff, sizeof(sendbuff)); break; } case OP_SO_RCVBUF: { u32 recvbuff = *(u32*)optval.get_ptr(); ret = ::setsockopt(sock->s, SOL_SOCKET, SO_RCVBUF, (const char*)&recvbuff, sizeof(recvbuff)); break; } case OP_SO_SNDTIMEO: { u32 sendtimeout = *(u32*)optval.get_ptr(); ret = ::setsockopt(sock->s, SOL_SOCKET, SO_SNDTIMEO, (char*)&sendtimeout, sizeof(sendtimeout)); break; } case OP_SO_RCVTIMEO: { u32 recvtimeout = *(u32*)optval.get_ptr(); ret = ::setsockopt(sock->s, SOL_SOCKET, SO_RCVTIMEO, (char*)&recvtimeout, sizeof(recvtimeout)); break; } case OP_SO_SNDLOWAT: { u32 sendlowmark = *(u32*)optval.get_ptr(); ret = ::setsockopt(sock->s, SOL_SOCKET, SO_SNDLOWAT, (char*)&sendlowmark, sizeof(sendlowmark)); break; } case OP_SO_RCVLOWAT: { u32 recvlowmark = *(u32*)optval.get_ptr(); ret = ::setsockopt(sock->s, SOL_SOCKET, SO_RCVLOWAT, (char*)&recvlowmark, sizeof(recvlowmark)); break; } case OP_SO_USECRYPTO: { libnet.warning("Socket option OP_SO_USECRYPTO is unimplemented"); break; } case OP_SO_USESIGNATURE: { libnet.warning("Socket option OP_SO_USESIGNATURE is unimplemented"); break; } case OP_SO_BROADCAST: { u32 enablebroadcast = *(u32*)optval.get_ptr(); ret = ::setsockopt(sock->s, SOL_SOCKET, SO_BROADCAST, (char*)&enablebroadcast, sizeof(enablebroadcast)); break; } case OP_SO_REUSEADDR: { u32 reuseaddr = *(u32*)optval.get_ptr(); ret = ::setsockopt(sock->s, SOL_SOCKET, SO_REUSEADDR, (char*)&reuseaddr, sizeof(reuseaddr)); break; } default: libnet.error("Unknown socket option for Win32: 0x%x", optname); } } else if (level == PROTO_IPPROTO_TCP) { switch (optname) { case OP_TCP_NODELAY: { const char delay = *(char*)optval.get_ptr(); ret = ::setsockopt(sock->s, IPPROTO_TCP, TCP_NODELAY, &delay, sizeof(delay)); break; } case OP_TCP_MAXSEG: { libnet.warning("TCP_MAXSEG can't be set on Windows."); break; } default: libnet.error("Unknown TCP option for Win32: 0x%x", optname); } } #else if (level == SOL_SOCKET) { switch (optname) { case OP_SO_NBIO: { // Obtain the flags s32 flags = fcntl(s, F_GETFL, 0); if (flags < 0) { fmt::throw_exception("Failed to obtain socket flags." HERE); } u32 mode = *(u32*)optval.get_ptr(); flags = mode ? (flags &~O_NONBLOCK) : (flags | O_NONBLOCK); // Re-set the flags ret = fcntl(sock->s, F_SETFL, flags); break; } default: libnet.error("Unknown socket option for Unix: 0x%x", optname); } } else if (level == PROTO_IPPROTO_TCP) { switch (optname) { case OP_TCP_NODELAY: { u32 delay = *(u32*)optval.get_ptr(); ret = ::setsockopt(sock->s, IPPROTO_TCP, TCP_NODELAY, &delay, optlen); break; } case OP_TCP_MAXSEG: { u32 maxseg = *(u32*)optval.get_ptr(); ret = ::setsockopt(sock->s, IPPROTO_TCP, TCP_MAXSEG, &maxseg, optlen); break; } default: libnet.error("Unknown TCP option for Unix: 0x%x", optname); } } #endif if (ret != 0) { libnet.error("setsockopt(): error %d", get_errno() = get_last_error()); return -1; } return ret; }
vm::ptr<s32> _sys_net_errno_loc() { libnet.warning("_sys_net_errno_loc()"); return get_errno().ptr(); }
int select(int nfds, FAR fd_set *readfds, FAR fd_set *writefds, FAR fd_set *exceptfds, FAR struct timeval *timeout) { struct pollfd *pollset; int errcode = OK; int fd; int npfds; int msec; int ndx; int ret; /* select() is cancellation point */ (void)enter_cancellation_point(); /* How many pollfd structures do we need to allocate? */ /* Initialize the descriptor list for poll() */ for (fd = 0, npfds = 0; fd < nfds; fd++) { /* Check if any monitor operation is requested on this fd */ if ((readfds && FD_ISSET(fd, readfds)) || (writefds && FD_ISSET(fd, writefds)) || (exceptfds && FD_ISSET(fd, exceptfds))) { /* Yes.. increment the count of pollfds structures needed */ npfds++; } } /* Allocate the descriptor list for poll() */ pollset = (struct pollfd *)kmm_zalloc(npfds * sizeof(struct pollfd)); if (!pollset) { set_errno(ENOMEM); leave_cancellation_point(); return ERROR; } /* Initialize the descriptor list for poll() */ for (fd = 0, ndx = 0; fd < nfds; fd++) { int incr = 0; /* The readfs set holds the set of FDs that the caller can be assured * of reading from without blocking. Note that POLLHUP is included as * a read-able condition. POLLHUP will be reported at the end-of-file * or when a connection is lost. In either case, the read() can then * be performed without blocking. */ if (readfds && FD_ISSET(fd, readfds)) { pollset[ndx].fd = fd; pollset[ndx].events |= POLLIN; incr = 1; } /* The writefds set holds the set of FDs that the caller can be assured * of writing to without blocking. */ if (writefds && FD_ISSET(fd, writefds)) { pollset[ndx].fd = fd; pollset[ndx].events |= POLLOUT; incr = 1; } /* The exceptfds set holds the set of FDs that are watched for exceptions */ if (exceptfds && FD_ISSET(fd, exceptfds)) { pollset[ndx].fd = fd; incr = 1; } ndx += incr; } DEBUGASSERT(ndx == npfds); /* Convert the timeout to milliseconds */ if (timeout) { /* Calculate the timeout in milliseconds */ msec = timeout->tv_sec * 1000 + timeout->tv_usec / 1000; } else { /* Any negative value of msec means no timeout */ msec = -1; } /* Then let poll do all of the real work. */ ret = poll(pollset, npfds, msec); if (ret < 0) { /* poll() failed! Save the errno value */ errcode = get_errno(); } /* Now set up the return values */ if (readfds) { memset(readfds, 0, sizeof(fd_set)); } if (writefds) { memset(writefds, 0, sizeof(fd_set)); } if (exceptfds) { memset(exceptfds, 0, sizeof(fd_set)); } /* Convert the poll descriptor list back into selects 3 bitsets */ if (ret > 0) { ret = 0; for (ndx = 0; ndx < npfds; ndx++) { /* Check for read conditions. Note that POLLHUP is included as a * read condition. POLLHUP will be reported when no more data will * be available (such as when a connection is lost). In either * case, the read() can then be performed without blocking. */ if (readfds) { if (pollset[ndx].revents & (POLLIN | POLLHUP)) { FD_SET(pollset[ndx].fd, readfds); ret++; } } /* Check for write conditions */ if (writefds) { if (pollset[ndx].revents & POLLOUT) { FD_SET(pollset[ndx].fd, writefds); ret++; } } /* Check for exceptions */ if (exceptfds) { if (pollset[ndx].revents & POLLERR) { FD_SET(pollset[ndx].fd, exceptfds); ret++; } } } } kmm_free(pollset); /* Did poll() fail above? */ if (ret < 0) { /* Yes.. restore the errno value */ set_errno(errcode); } leave_cancellation_point(); return ret; }
int lib_hostfile_lookup(FAR const void *addr, socklen_t len, int type, FAR struct hostent *host, FAR char *buf, size_t buflen, int *h_errnop) { FAR FILE *stream; int herrnocode; int nread; /* Search the hosts file for a match */ stream = fopen(CONFIG_NETDB_HOSTCONF_PATH, "r"); if (stream == NULL) { int errcode = get_errno(); nerr("ERROR: Failed to open the hosts file %s: %d\n", CONFIG_NETDB_HOSTCONF_PATH, errcode); UNUSED(errcode); herrnocode = NO_RECOVERY; goto errorout_with_herrnocode; } /* Loop reading entries from the hosts file until a match is found or * until we hit the end-of-file. */ do { /* Read the next entry from the hosts file */ nread = lib_parse_hostfile(stream, host, buf, buflen); if (nread < 0) { /* Possible errors: * ERANGE - Buffer not big enough * ESPIPE - End of file (or possibly a read error). * EAGAIN - Error parsing the line (E.g., missing hostname) */ if (nread == -ESPIPE) { nread = 0; } else if (nread != -EAGAIN) { herrnocode = NO_RECOVERY; goto errorout_with_stream; } } else if (nread > 0 && len == host->h_length && type == host->h_addrtype) { /* We successfully read the entry and the type and size of the * address is good. Now compare the addresses: */ FAR char *hostaddr = host->h_addr; if (hostaddr != NULL) { ninfo("Comparing addresses...\n"); if (memcmp(addr, hostaddr, len) == 0) { /* We have a match */ fclose(stream); return OK; } } } } while (nread != 0); /* We get here when the end of the hosts file is encountered without * finding the hostname. */ herrnocode = HOST_NOT_FOUND; errorout_with_stream: fclose(stream); errorout_with_herrnocode: if (h_errnop) { *h_errnop = herrnocode; } return ERROR; }
int task_spawn(FAR pid_t *pid, FAR const char *name, main_t entry, FAR const posix_spawn_file_actions_t *file_actions, FAR const posix_spawnattr_t *attr, FAR char *const argv[], FAR char *const envp[]) { struct sched_param param; pid_t proxy; #ifdef CONFIG_SCHED_WAITPID int status; #endif int ret; svdbg("pid=%p name=%s entry=%p file_actions=%p attr=%p argv=%p\n", pid, name, entry, file_actions, attr, argv); /* If there are no file actions to be performed and there is no change to * the signal mask, then start the new child task directly from the parent task. */ #ifndef CONFIG_DISABLE_SIGNALS if ((file_actions == NULL || *file_actions == NULL) && (attr == NULL || (attr->flags & POSIX_SPAWN_SETSIGMASK) == 0)) #else if (file_actions == NULL || *file_actions == NULL) #endif { return task_spawn_exec(pid, name, entry, attr, argv); } /* Otherwise, we will have to go through an intermediary/proxy task in order * to perform the I/O redirection. This would be a natural place to fork(). * However, true fork() behavior requires an MMU and most implementations * of vfork() are not capable of these operations. * * Even without fork(), we can still do the job, but parameter passing is * messier. Unfortunately, there is no (clean) way to pass binary values * as a task parameter, so we will use a semaphore-protected global * structure. */ /* Get exclusive access to the global parameter structure */ spawn_semtake(&g_spawn_parmsem); /* Populate the parameter structure */ g_spawn_parms.result = ENOSYS; g_spawn_parms.pid = pid; g_spawn_parms.file_actions = file_actions ? *file_actions : NULL; g_spawn_parms.attr = attr; g_spawn_parms.argv = argv; g_spawn_parms.u.task.name = name; g_spawn_parms.u.task.entry = entry; /* Get the priority of this (parent) task */ ret = sched_getparam(0, ¶m); if (ret < 0) { int errcode = get_errno(); sdbg("ERROR: sched_getparam failed: %d\n", errcode); spawn_semgive(&g_spawn_parmsem); return errcode; } /* Disable pre-emption so that the proxy does not run until waitpid * is called. This is probably unnecessary since the task_spawn_proxy has * the same priority as this thread; it should be schedule behind this * task in the ready-to-run list. */ #ifdef CONFIG_SCHED_WAITPID sched_lock(); #endif /* Start the intermediary/proxy task at the same priority as the parent * task. */ proxy = task_create("task_spawn_proxy", param.sched_priority, CONFIG_POSIX_SPAWN_PROXY_STACKSIZE, (main_t)task_spawn_proxy, (FAR char * const*)NULL); if (proxy < 0) { ret = get_errno(); sdbg("ERROR: Failed to start task_spawn_proxy: %d\n", ret); goto errout_with_lock; } /* Wait for the proxy to complete its job */ #ifdef CONFIG_SCHED_WAITPID ret = waitpid(proxy, &status, 0); if (ret < 0) { sdbg("ERROR: waitpid() failed: %d\n", errno); goto errout_with_lock; } #else spawn_semtake(&g_spawn_execsem); #endif /* Get the result and relinquish our access to the parameter structure */ ret = g_spawn_parms.result; errout_with_lock: #ifdef CONFIG_SCHED_WAITPID sched_unlock(); #endif spawn_semgive(&g_spawn_parmsem); return ret; }
bool ubgps_check_alp_file_validity(const char *filepath) { bool ret = false; uint8_t buf[2]; ssize_t rlen; int fd; fd = open(filepath, O_RDONLY); if (fd < 0) { dbg("could not open file: \"%s\" (errno=%d)\n", filepath, get_errno()); goto out; } /* Get header */ rlen = read(fd, buf, 2); if (rlen < 2) { dbg("could not read header, rlen=%d, errno=%d\n", rlen, get_errno()); goto out; } /* Expected header is 'µB' */ if (!(buf[0] == 0xB5 && buf[1] == 0x62)) { dbg("invalid header, %02X:%02X\n", buf[0], buf[1]); goto out; } #if 0 /* Get tail */ rlen = lseek(fd, -2, SEEK_END); if (rlen == -1) { dbg("could not seek to tail, rlen=%d, errno=%d\n", rlen, get_errno()); goto out; } rlen = read(fd, buf, 2); if (rlen < 2) { dbg("could not read tail, rlen=%d, errno=%d\n", rlen, get_errno()); goto out; } /* Expected tail is 'XX' */ if (!(buf[0] == 'X' && buf[1] == 'X')) { dbg("invalid tail, %02X:%02X\n", buf[0], buf[1]); goto out; } #endif /* ALP file appears to be valid. */ ret = true; out: if (fd >= 0) { close(fd); } return ret; }
int sam_ajoy_initialization(void) { int ret; int fd; int i; /* Initialize ADC. We will need this to read the ADC inputs */ ret = board_adc_initialize(); if (ret < 0) { ierr("ERROR: board_adc_initialize() failed: %d\n", ret); return ret; } /* Open the ADC driver for reading. */ fd = open("/dev/adc0", O_RDONLY); if (fd < 0) { int errcode = get_errno(); ierr("ERROR: Failed to open /dev/adc0: %d\n", errcode); return -errcode; } /* Detach the file structure from the file descriptor so that it can be * used on any thread. */ ret = file_detach(fd, &g_adcfile); if (ret < 0) { ierr("ERROR: Failed to detach from file descriptor: %d\n", ret); (void)close(fd); return ret; } /* Configure the GPIO pins as interrupting inputs. */ for (i = 0; i < AJOY_NGPIOS; i++) { /* Configure the PIO as an input */ sam_configpio(g_joypio[i]); /* Configure PIO interrupts, attach the interrupt handler, but leave * the interrupt disabled. */ sam_pioirq(g_joypio[i]); (void)irq_attach(g_joyirq[i], ajoy_interrupt); sam_pioirqdisable(g_joyirq[i]); } /* Register the joystick device as /dev/ajoy0 */ ret = ajoy_register("/dev/ajoy0", &g_ajoylower); if (ret < 0) { ierr("ERROR: ajoy_register failed: %d\n", ret); file_close_detached(&g_adcfile); } return ret; }
int pthread_create(FAR pthread_t *thread, FAR const pthread_attr_t *attr, pthread_startroutine_t start_routine, pthread_addr_t arg) { FAR struct pthread_tcb_s *ptcb; FAR struct join_s *pjoin; struct sched_param param; int policy; int errcode; pid_t pid; int ret; #ifdef HAVE_TASK_GROUP bool group_joined = false; #endif /* If attributes were not supplied, use the default attributes */ if (!attr) { attr = &g_default_pthread_attr; } /* Allocate a TCB for the new task. */ ptcb = (FAR struct pthread_tcb_s *)kmm_zalloc(sizeof(struct pthread_tcb_s)); if (!ptcb) { sdbg("ERROR: Failed to allocate TCB\n"); return ENOMEM; } #ifdef HAVE_TASK_GROUP /* Bind the parent's group to the new TCB (we have not yet joined the * group). */ ret = group_bind(ptcb); if (ret < 0) { errcode = ENOMEM; goto errout_with_tcb; } #endif #ifdef CONFIG_ARCH_ADDRENV /* Share the address environment of the parent task group. */ ret = up_addrenv_attach(ptcb->cmn.group, (FAR struct tcb_s *)g_readytorun.head); if (ret < 0) { errcode = -ret; goto errout_with_tcb; } #endif /* Allocate a detachable structure to support pthread_join logic */ pjoin = (FAR struct join_s *)kmm_zalloc(sizeof(struct join_s)); if (!pjoin) { sdbg("ERROR: Failed to allocate join\n"); errcode = ENOMEM; goto errout_with_tcb; } /* Allocate the stack for the TCB */ ret = up_create_stack((FAR struct tcb_s *)ptcb, attr->stacksize, TCB_FLAG_TTYPE_PTHREAD); if (ret != OK) { errcode = ENOMEM; goto errout_with_join; } /* Should we use the priority and scheduler specified in the pthread * attributes? Or should we use the current thread's priority and * scheduler? */ if (attr->inheritsched == PTHREAD_INHERIT_SCHED) { /* Get the priority (and any other scheduling parameters) for this * thread. */ ret = sched_getparam(0, ¶m); if (ret == ERROR) { errcode = get_errno(); goto errout_with_join; } /* Get the scheduler policy for this thread */ policy = sched_getscheduler(0); if (policy == ERROR) { errcode = get_errno(); goto errout_with_join; } } else { /* Use the scheduler policy and policy the attributes */ policy = attr->policy; param.sched_priority = attr->priority; #ifdef CONFIG_SCHED_SPORADIC param.sched_ss_low_priority = attr->low_priority; param.sched_ss_max_repl = attr->max_repl; param.sched_ss_repl_period.tv_sec = attr->repl_period.tv_sec; param.sched_ss_repl_period.tv_nsec = attr->repl_period.tv_nsec; param.sched_ss_init_budget.tv_sec = attr->budget.tv_sec; param.sched_ss_init_budget.tv_nsec = attr->budget.tv_nsec; #endif } #ifdef CONFIG_SCHED_SPORADIC if (policy == SCHED_SPORADIC) { FAR struct sporadic_s *sporadic; int repl_ticks; int budget_ticks; /* Convert timespec values to system clock ticks */ (void)clock_time2ticks(¶m.sched_ss_repl_period, &repl_ticks); (void)clock_time2ticks(¶m.sched_ss_init_budget, &budget_ticks); /* The replenishment period must be greater than or equal to the * budget period. */ if (repl_ticks < budget_ticks) { errcode = EINVAL; goto errout_with_join; } /* Initialize the sporadic policy */ ret = sched_sporadic_initialize(&ptcb->cmn); if (ret >= 0) { sporadic = ptcb->cmn.sporadic; DEBUGASSERT(sporadic != NULL); /* Save the sporadic scheduling parameters */ sporadic->hi_priority = param.sched_priority; sporadic->low_priority = param.sched_ss_low_priority; sporadic->max_repl = param.sched_ss_max_repl; sporadic->repl_period = repl_ticks; sporadic->budget = budget_ticks; /* And start the first replenishment interval */ ret = sched_sporadic_start(&ptcb->cmn); } /* Handle any failures */ if (ret < 0) { errcode = -ret; goto errout_with_join; } } #endif /* Initialize the task control block */ ret = pthread_schedsetup(ptcb, param.sched_priority, pthread_start, start_routine); if (ret != OK) { errcode = EBUSY; goto errout_with_join; } /* Configure the TCB for a pthread receiving on parameter * passed by value */ pthread_argsetup(ptcb, arg); #ifdef HAVE_TASK_GROUP /* Join the parent's task group */ ret = group_join(ptcb); if (ret < 0) { errcode = ENOMEM; goto errout_with_join; } group_joined = true; #endif /* Attach the join info to the TCB. */ ptcb->joininfo = (FAR void *)pjoin; /* Set the appropriate scheduling policy in the TCB */ ptcb->cmn.flags &= ~TCB_FLAG_POLICY_MASK; switch (policy) { default: DEBUGPANIC(); case SCHED_FIFO: ptcb->cmn.flags |= TCB_FLAG_SCHED_FIFO; break; #if CONFIG_RR_INTERVAL > 0 case SCHED_RR: ptcb->cmn.flags |= TCB_FLAG_SCHED_RR; ptcb->cmn.timeslice = MSEC2TICK(CONFIG_RR_INTERVAL); break; #endif #ifdef CONFIG_SCHED_SPORADIC case SCHED_SPORADIC: ptcb->cmn.flags |= TCB_FLAG_SCHED_SPORADIC; break; #endif #if 0 /* Not supported */ case SCHED_OTHER: ptcb->cmn.flags |= TCB_FLAG_SCHED_OTHER; break; #endif } /* Get the assigned pid before we start the task (who knows what * could happen to ptcb after this!). Copy this ID into the join structure * as well. */ pid = (int)ptcb->cmn.pid; pjoin->thread = (pthread_t)pid; /* Initialize the semaphores in the join structure to zero. */ ret = sem_init(&pjoin->data_sem, 0, 0); if (ret == OK) { ret = sem_init(&pjoin->exit_sem, 0, 0); } /* Activate the task */ sched_lock(); if (ret == OK) { ret = task_activate((FAR struct tcb_s *)ptcb); } if (ret == OK) { /* Wait for the task to actually get running and to register * its join structure. */ (void)pthread_takesemaphore(&pjoin->data_sem); /* Return the thread information to the caller */ if (thread) { *thread = (pthread_t)pid; } if (!pjoin->started) { ret = EINVAL; } sched_unlock(); (void)sem_destroy(&pjoin->data_sem); } else { sched_unlock(); dq_rem((FAR dq_entry_t *)ptcb, (FAR dq_queue_t *)&g_inactivetasks); (void)sem_destroy(&pjoin->data_sem); (void)sem_destroy(&pjoin->exit_sem); errcode = EIO; goto errout_with_join; } return ret; errout_with_join: sched_kfree(pjoin); ptcb->joininfo = NULL; errout_with_tcb: #ifdef HAVE_TASK_GROUP /* Clear group binding */ if (ptcb && !group_joined) { ptcb->cmn.group = NULL; } #endif sched_releasetcb((FAR struct tcb_s *)ptcb, TCB_FLAG_TTYPE_PTHREAD); return errcode; }
/* do_syscall() should always have a single exit point at the end so that actions, such as logging of syscall results, can be performed. All errnos that do_syscall() returns must be -TARGET_<errcode>. */ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6, abi_long arg7, abi_long arg8) { abi_long ret; void *p; #ifdef DEBUG gemu_log("freebsd syscall %d\n", num); #endif if(do_strace) print_freebsd_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6); switch(num) { case TARGET_FREEBSD_NR_exit: #ifdef TARGET_GPROF _mcleanup(); #endif gdb_exit(cpu_env, arg1); /* XXX: should free thread stack and CPU env */ _exit(arg1); ret = 0; /* avoid warning */ break; case TARGET_FREEBSD_NR_read: if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0))) goto efault; ret = get_errno(read(arg1, p, arg3)); unlock_user(p, arg2, ret); break; case TARGET_FREEBSD_NR_write: if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1))) goto efault; ret = get_errno(write(arg1, p, arg3)); unlock_user(p, arg2, 0); break; case TARGET_FREEBSD_NR_writev: { int count = arg3; struct iovec *vec; vec = alloca(count * sizeof(struct iovec)); if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0) goto efault; ret = get_errno(writev(arg1, vec, count)); unlock_iovec(vec, arg2, count, 0); } break; case TARGET_FREEBSD_NR_open: if (!(p = lock_user_string(arg1))) goto efault; ret = get_errno(open(path(p), target_to_host_bitmask(arg2, fcntl_flags_tbl), arg3)); unlock_user(p, arg1, 0); break; case TARGET_FREEBSD_NR_mmap: ret = get_errno(target_mmap(arg1, arg2, arg3, target_to_host_bitmask(arg4, mmap_flags_tbl), arg5, arg6)); break; case TARGET_FREEBSD_NR_mprotect: ret = get_errno(target_mprotect(arg1, arg2, arg3)); break; case TARGET_FREEBSD_NR_break: ret = do_obreak(arg1); break; #ifdef __FreeBSD__ case TARGET_FREEBSD_NR___sysctl: ret = do_freebsd_sysctl(arg1, arg2, arg3, arg4, arg5, arg6); break; #endif case TARGET_FREEBSD_NR_sysarch: ret = do_freebsd_sysarch(cpu_env, arg1, arg2); break; case TARGET_FREEBSD_NR_syscall: case TARGET_FREEBSD_NR___syscall: ret = do_freebsd_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,arg7,arg8,0); break; default: ret = get_errno(syscall(num, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)); break; } fail: #ifdef DEBUG gemu_log(" = %ld\n", ret); #endif if (do_strace) print_freebsd_syscall_ret(num, ret); return ret; efault: ret = -TARGET_EFAULT; goto fail; }
int schedule_unload(pid_t pid, FAR struct binary_s *bin) { struct sigaction act; struct sigaction oact; sigset_t sigset; irqstate_t flags; int errorcode; int ret; /* Make sure that SIGCHLD is unmasked */ (void)sigemptyset(&sigset); (void)sigaddset(&sigset, SIGCHLD); ret = sigprocmask(SIG_UNBLOCK, &sigset, NULL); if (ret != OK) { /* The errno value will get trashed by the following debug output */ errorcode = get_errno(); bvdbg("ERROR: sigprocmask failed: %d\n", ret); goto errout; } /* Add the structure to the list. We want to do this *before* connecting * the signal handler. This does, however, make error recovery more * complex if sigaction() fails below because then we have to remove the * unload structure for the list in an unexpected context. */ unload_list_add(pid, bin); /* Register the SIGCHLD handler */ act.sa_sigaction = unload_callback; act.sa_flags = SA_SIGINFO; (void)sigfillset(&act.sa_mask); (void)sigdelset(&act.sa_mask, SIGCHLD); ret = sigaction(SIGCHLD, &act, &oact); if (ret != OK) { /* The errno value will get trashed by the following debug output */ errorcode = get_errno(); bvdbg("ERROR: sigaction failed: %d\n" , ret); /* Emergency removal from the list */ flags = irqsave(); if (unload_list_remove(pid) != bin) { blldbg("ERROR: Failed to remove structure\n"); } goto errout; } return OK; errout: set_errno(errorcode); return ERROR; }
abi_long do_openbsd_syscall(void *cpu_env, int num, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6) { abi_long ret; void *p; #ifdef DEBUG gemu_log("openbsd syscall %d\n", num); #endif if(do_strace) print_openbsd_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6); switch(num) { case TARGET_OPENBSD_NR_exit: #ifdef TARGET_GPROF _mcleanup(); #endif gdb_exit(cpu_env, arg1); /* XXX: should free thread stack and CPU env */ _exit(arg1); ret = 0; /* avoid warning */ break; case TARGET_OPENBSD_NR_read: if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0))) goto efault; ret = get_errno(read(arg1, p, arg3)); unlock_user(p, arg2, ret); break; case TARGET_OPENBSD_NR_write: if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1))) goto efault; ret = get_errno(write(arg1, p, arg3)); unlock_user(p, arg2, 0); break; case TARGET_OPENBSD_NR_open: if (!(p = lock_user_string(arg1))) goto efault; ret = get_errno(open(path(p), target_to_host_bitmask(arg2, fcntl_flags_tbl), arg3)); unlock_user(p, arg1, 0); break; case TARGET_OPENBSD_NR_mmap: ret = get_errno(target_mmap(arg1, arg2, arg3, target_to_host_bitmask(arg4, mmap_flags_tbl), arg5, arg6)); break; case TARGET_OPENBSD_NR_mprotect: ret = get_errno(target_mprotect(arg1, arg2, arg3)); break; case TARGET_OPENBSD_NR_syscall: case TARGET_OPENBSD_NR___syscall: ret = do_openbsd_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0); break; default: ret = syscall(num, arg1, arg2, arg3, arg4, arg5, arg6); break; } fail: #ifdef DEBUG gemu_log(" = %ld\n", ret); #endif if (do_strace) print_openbsd_syscall_ret(num, ret); return ret; efault: ret = -TARGET_EFAULT; goto fail; }
static ssize_t _gnutls_dgram_read (gnutls_session_t session, mbuffer_st **bufel, gnutls_pull_func pull_func) { ssize_t i, ret; char *ptr; size_t max_size = _gnutls_get_max_decrypted_data(session); size_t recv_size = MAX_RECV_SIZE(session); gnutls_transport_ptr_t fd = session->internals.transport_recv_ptr; if (recv_size > max_size) recv_size = max_size; *bufel = _mbuffer_alloc (0, max_size); if (*bufel == NULL) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); ptr = (*bufel)->msg.data; session->internals.direction = 0; reset_errno (session); i = pull_func (fd, ptr, recv_size); if (i < 0) { int err = get_errno (session); _gnutls_read_log ("READ: %d returned from %p, errno=%d gerrno=%d\n", (int) i, fd, errno, session->internals.errnum); if (err == EAGAIN) { ret = GNUTLS_E_AGAIN; goto cleanup; } else if (err == EINTR) { ret = GNUTLS_E_INTERRUPTED; goto cleanup; } else { gnutls_assert (); ret = GNUTLS_E_PULL_ERROR; goto cleanup; } } else { _gnutls_read_log ("READ: Got %d bytes from %p\n", (int) i, fd); if (i == 0) { /* If we get here, we likely have a stream socket. * FIXME: this probably breaks DCCP. */ gnutls_assert (); ret = 0; goto cleanup; } _mbuffer_set_udata_size (*bufel, i); } _gnutls_read_log ("READ: read %d bytes from %p\n", (int) i, fd); return i; cleanup: _mbuffer_xfree(bufel); return ret; }
static int ajoy_sample(FAR const struct ajoy_lowerhalf_s *lower, FAR struct ajoy_sample_s *sample) { struct adc_msg_s adcmsg[SAM_ADC_NCHANNELS]; FAR struct adc_msg_s *ptr; ssize_t nread; ssize_t offset; int have; int i; /* Read all of the available samples (handling the case where additional * channels are enabled). */ nread = file_read(&g_adcfile, adcmsg, MAX_ADC_CHANNELS * sizeof(struct adc_msg_s)); if (nread < 0) { int errcode = get_errno(); if (errcode != EINTR) { ierr("ERROR: read failed: %d\n", errcode); } return -errcode; } else if (nread < 2 * sizeof(struct adc_msg_s)) { ierr("ERROR: read too small: %ld\n", (long)nread); return -EIO; } /* Sample and the raw analog inputs */ for (i = 0, offset = 0, have = 0; i < SAM_ADC_NCHANNELS && offset < nread && have != 3; i++, offset += sizeof(struct adc_msg_s)) { ptr = &adcmsg[i]; /* Is this one of the channels that we need? */ if ((have & 1) == 0 && ptr->am_channel == 0) { int32_t tmp = ptr->am_data; sample->as_x = (int16_t)tmp; have |= 1; iinfo("X sample: %ld -> %d\n", (long)tmp, (int)sample->as_x); } if ((have & 2) == 0 && ptr->am_channel == 1) { int32_t tmp = ptr->am_data; sample->as_y = (int16_t)tmp; have |= 2; iinfo("Y sample: %ld -> %d\n", (long)tmp, (int)sample->as_y); } } if (have != 3) { ierr("ERROR: Could not find joystack channels\n"); return -EIO; } /* Sample the discrete button inputs */ sample->as_buttons = ajoy_buttons(lower); iinfo("Returning: %02x\n", AJOY_SUPPORTED); return OK; }
int read(int fid, void *buf, unsigned int nbytes) { int hchar = 0, read = 0; FILE *file; /*-------------------------------------------------------------------*/ /* If number of requested bytes is zero, return zero. */ /*-------------------------------------------------------------------*/ if (nbytes == 0) return 0; #if OS_PARM_CHECK /*-------------------------------------------------------------------*/ /* Ensure file descriptor is valid. */ /*-------------------------------------------------------------------*/ if (fid < 0 || fid >= FOPEN_MAX) { set_errno(EBADF); return -1; } /*-------------------------------------------------------------------*/ /* Return error if buffer pointer is invalid. */ /*-------------------------------------------------------------------*/ if (buf == NULL) { Files[fid].errcode = EFAULT; set_errno(EFAULT); return -1; } #endif /*-------------------------------------------------------------------*/ /* Acquire exclusive read access to file. */ /*-------------------------------------------------------------------*/ file = &Files[fid]; file->acquire(file, F_READ); /*-------------------------------------------------------------------*/ /* Return error if file is closed. */ /*-------------------------------------------------------------------*/ if (file->ioctl == NULL) { set_errno(EBADF); file->release(file, F_READ); return -1; } /*-------------------------------------------------------------------*/ /* If available, read pushed-back character first. */ /*-------------------------------------------------------------------*/ if (file->hold_char) { ui8 *cp = buf; *cp = (ui8)file->hold_char; buf = cp + 1; file->hold_char = 0; hchar = 1; --nbytes; } /*-------------------------------------------------------------------*/ /* Check if there are more characters to read. */ /*-------------------------------------------------------------------*/ if (nbytes) { /*-----------------------------------------------------------------*/ /* Pass read request to file system or device driver. */ /*-----------------------------------------------------------------*/ read = file->read(file, buf, nbytes); /*-----------------------------------------------------------------*/ /* Read error is disregarded iff pushed-back character was read. */ /*-----------------------------------------------------------------*/ if (read == -1) { if (hchar) read = 0; else file->errcode = get_errno(); } } /*-------------------------------------------------------------------*/ /* Release exclusive read access to file. */ /*-------------------------------------------------------------------*/ file->release(file, F_READ); /*-------------------------------------------------------------------*/ /* Return number of bytes successfully read or -1. */ /*-------------------------------------------------------------------*/ return read + hchar; }
int sem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime) { FAR struct tcb_s *rtcb = this_task(); irqstate_t flags; int ticks; int errcode; int ret = ERROR; DEBUGASSERT(up_interrupt_context() == false && rtcb->waitdog == NULL); /* Verify the input parameters and, in case of an error, set * errno appropriately. */ #ifdef CONFIG_DEBUG if (!abstime || !sem) { errcode = EINVAL; goto errout; } #endif /* Create a watchdog. We will not actually need this watchdog * unless the semaphore is unavailable, but we will reserve it up * front before we enter the following critical section. */ rtcb->waitdog = wd_create(); if (!rtcb->waitdog) { errcode = ENOMEM; goto errout; } /* We will disable interrupts until we have completed the semaphore * wait. We need to do this (as opposed to just disabling pre-emption) * because there could be interrupt handlers that are asynchronously * posting semaphores and to prevent race conditions with watchdog * timeout. This is not too bad because interrupts will be re- * enabled while we are blocked waiting for the semaphore. */ flags = irqsave(); /* Try to take the semaphore without waiting. */ ret = sem_trywait(sem); if (ret == OK) { /* We got it! */ goto success_with_irqdisabled; } /* We will have to wait for the semaphore. Make sure that we were provided * with a valid timeout. */ if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) { errcode = EINVAL; goto errout_with_irqdisabled; } /* Convert the timespec to clock ticks. We must have interrupts * disabled here so that this time stays valid until the wait begins. */ errcode = clock_abstime2ticks(CLOCK_REALTIME, abstime, &ticks); /* If the time has already expired return immediately. */ if (errcode == OK && ticks <= 0) { errcode = ETIMEDOUT; goto errout_with_irqdisabled; } /* Handle any time-related errors */ if (errcode != OK) { goto errout_with_irqdisabled; } /* Start the watchdog */ (void)wd_start(rtcb->waitdog, ticks, (wdentry_t)sem_timeout, 1, getpid()); /* Now perform the blocking wait */ ret = sem_wait(sem); if (ret < 0) { /* sem_wait() failed. Save the errno value */ errcode = get_errno(); } /* Stop the watchdog timer */ wd_cancel(rtcb->waitdog); if (errcode != OK) { goto errout_with_irqdisabled; } /* We can now restore interrupts and delete the watchdog */ /* Success exits */ success_with_irqdisabled: irqrestore(flags); wd_delete(rtcb->waitdog); rtcb->waitdog = NULL; return OK; /* Error exits */ errout_with_irqdisabled: irqrestore(flags); wd_delete(rtcb->waitdog); rtcb->waitdog = NULL; errout: set_errno(errcode); return ERROR; }
int psock_tcp_accept(FAR struct socket *psock, FAR struct sockaddr *addr, FAR socklen_t *addrlen, FAR void **newconn) { FAR struct tcp_conn_s *conn; struct accept_s state; int ret; DEBUGASSERT(psock && newconn); /* Check the backlog to see if there is a connection already pending for * this listener. */ conn = (FAR struct tcp_conn_s *)psock->s_conn; #ifdef CONFIG_NET_TCPBACKLOG state.acpt_newconn = tcp_backlogremove(conn); if (state.acpt_newconn) { /* Yes... get the address of the connected client */ nvdbg("Pending conn=%p\n", state.acpt_newconn); accept_tcpsender(psock, state.acpt_newconn, addr, addrlen); } /* In general, this uIP-based implementation will not support non-blocking * socket operations... except in a few cases: Here for TCP accept with * backlog enabled. If this socket is configured as non-blocking then * return EAGAIN if there is no pending connection in the backlog. */ else if (_SS_ISNONBLOCK(psock->s_flags)) { return -EAGAIN; } else #endif { /* Set the socket state to accepting */ psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_ACCEPT); /* Perform the TCP accept operation */ /* Initialize the state structure. This is done with interrupts * disabled because we don't want anything to happen until we * are ready. */ state.acpt_sock = psock; state.acpt_addr = addr; state.acpt_addrlen = addrlen; state.acpt_newconn = NULL; state.acpt_result = OK; sem_init(&state.acpt_sem, 0, 0); /* Set up the callback in the connection */ conn->accept_private = (FAR void *)&state; conn->accept = accept_interrupt; /* Wait for the send to complete or an error to occur: NOTES: (1) * net_lockedwait will also terminate if a signal is received, (2) * interrupts may be disabled! They will be re-enabled while the * task sleeps and automatically re-enabled when the task restarts. */ ret = net_lockedwait(&state.acpt_sem); if (ret < 0) { /* The value returned by net_lockedwait() the same as the value * returned by sem_wait(): Zero (OK) is returned on success; -1 * (ERROR) is returned on a failure with the errno value set * appropriately. * * We have to preserve the errno value here because it may be * altered by intervening operations. */ ret = -get_errno(); DEBUGASSERT(ret < 0); } /* Make sure that no further interrupts are processed */ conn->accept_private = NULL; conn->accept = NULL; sem_destroy(&state. acpt_sem); /* Set the socket state to idle */ psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE); /* Check for a errors. Errors are signalled by negative errno values * for the send length. */ if (state.acpt_result != 0) { DEBUGASSERT(state.acpt_result > 0); return -state.acpt_result; } /* If net_lockedwait failed, then we were probably reawakened by a * signal. In this case, logic above will have set 'ret' to the * errno value returned by net_lockedwait(). */ if (ret < 0) { return ret; } } *newconn = (FAR void *)state.acpt_newconn; return OK; }
ssize_t nxffs_write(FAR struct file *filep, FAR const char *buffer, size_t buflen) { FAR struct nxffs_volume_s *volume; FAR struct nxffs_wrfile_s *wrfile; ssize_t remaining; ssize_t nwritten; ssize_t total; int ret; fvdbg("Write %d bytes to offset %d\n", buflen, filep->f_pos); /* Sanity checks */ DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); /* Recover the open file state from the struct file instance */ wrfile = (FAR struct nxffs_wrfile_s *)filep->f_priv; /* Recover the volume state from the open file */ volume = (FAR struct nxffs_volume_s *)filep->f_inode->i_private; DEBUGASSERT(volume != NULL); /* Get exclusive access to the volume. Note that the volume exclsem * protects the open file list. */ ret = sem_wait(&volume->exclsem); if (ret != OK) { ret = -get_errno(); fdbg("ERROR: sem_wait failed: %d\n", ret); goto errout; } /* Check if the file was opened with write access */ if ((wrfile->ofile.oflags & O_WROK) == 0) { fdbg("ERROR: File not open for write access\n"); ret = -EACCES; goto errout_with_semaphore; } /* Loop until we successfully appended all of the data to the file (or an * error occurs) */ for (total = 0; total < buflen; ) { remaining = buflen - total; /* Have we already allocated the data block? */ if (wrfile->doffset == 0) { /* No, allocate the data block now, re-packing if necessary. */ wrfile->datlen = 0; ret = nxffs_wralloc(volume, wrfile, remaining); if (ret < 0) { fdbg("ERROR: Failed to allocate a data block: %d\n", -ret); goto errout_with_semaphore; } } /* Seek to the FLASH block containing the data block */ nxffs_ioseek(volume, wrfile->doffset); /* Verify that the FLASH data that was previously written is still intact */ ret = nxffs_reverify(volume, wrfile); if (ret < 0) { fdbg("ERROR: Failed to verify FLASH data block: %d\n", -ret); goto errout_with_semaphore; } /* Append the data to the end of the data block and write the updated * block to flash. */ nwritten = nxffs_wrappend(volume, wrfile, &buffer[total], remaining); if (nwritten < 0) { fdbg("ERROR: Failed to append to FLASH to a data block: %d\n", -ret); goto errout_with_semaphore; } /* Decrement the number of bytes remaining to be written */ total += nwritten; } /* Success.. return the number of bytes written */ ret = total; filep->f_pos = wrfile->datlen; errout_with_semaphore: sem_post(&volume->exclsem); errout: return ret; }
static void output_skeleton (void) { FILE *m4_in = NULL; FILE *m4_out = NULL; char m4_in_file_name[] = "~m4_in_temp_file_XXXXXX"; char m4_out_file_name[] = "~m4_out_temp_file_XXXXXX"; // FILE *in; // int filter_fd[2]; char const *argv[10]; // pid_t pid; /* Compute the names of the package data dir and skeleton files. */ char const m4sugar[] = "m4sugar/m4sugar.m4"; char const m4bison[] = "bison.m4"; char *full_m4sugar; char *full_m4bison; char *full_skeleton; char const *p; char const *m4 = (p = getenv ("M4")) ? p : "M4"; int i = 0; char const *pkgdatadir = compute_pkgdatadir (); size_t skeleton_size = strlen (skeleton) + 1; size_t pkgdatadirlen = strlen (pkgdatadir); while (pkgdatadirlen && pkgdatadir[pkgdatadirlen - 1] == '/') pkgdatadirlen--; full_skeleton = xmalloc (pkgdatadirlen + 1 + (skeleton_size < sizeof m4sugar ? sizeof m4sugar : skeleton_size)); strncpy (full_skeleton, pkgdatadir, pkgdatadirlen); full_skeleton[pkgdatadirlen] = '/'; strcpy (full_skeleton + pkgdatadirlen + 1, m4sugar); full_m4sugar = xstrdup (full_skeleton); strcpy (full_skeleton + pkgdatadirlen + 1, m4bison); full_m4bison = xstrdup (full_skeleton); if (_mbschr (skeleton, '/')) strcpy (full_skeleton, skeleton); else strcpy (full_skeleton + pkgdatadirlen + 1, skeleton); /* Test whether m4sugar.m4 is readable, to check for proper installation. A faulty installation can cause deadlock, so a cheap sanity check is worthwhile. */ xfclose (xfopen (full_m4sugar, "r")); /* Create an m4 subprocess connected to us via two pipes. */ if (trace_flag & trace_tools) fprintf (stderr, "running: %s %s - %s %s\n", m4, full_m4sugar, full_m4bison, full_skeleton); /* Some future version of GNU M4 (most likely 1.6) may treat the -dV in a position-dependent manner. Keep it as the first argument so that all files are traced. See the thread starting at <http://lists.gnu.org/archive/html/bug-bison/2008-07/msg00000.html> for details. */ { argv[i++] = m4; /* When POSIXLY_CORRECT is set, GNU M4 1.6 and later disable GNU extensions, which Bison's skeletons depend on. With older M4, it has no effect. M4 1.4.12 added a -g/--gnu command-line option to make it explicit that a program wants GNU M4 extensions even when POSIXLY_CORRECT is set. See the thread starting at <http://lists.gnu.org/archive/html/bug-bison/2008-07/msg00000.html> for details. */ // if (*M4_GNU_OPTION) // argv[i++] = M4_GNU_OPTION; argv[i++] = "-I"; argv[i++] = pkgdatadir; if (trace_flag & trace_m4) argv[i++] = "-dV"; argv[i++] = full_m4sugar; argv[i++] = "-"; argv[i++] = full_m4bison; argv[i++] = full_skeleton; argv[i++] = NULL; aver (i <= ARRAY_CARDINALITY (argv)); /* The ugly cast is because gnulib gets the const-ness wrong. */ // pid = create_pipe_bidi ("m4", m4, (char **)(void*)argv, false, true, // true, filter_fd); } if (trace_flag & trace_muscles) muscles_output (stderr); { m4_in = mkstempFILE(m4_in_file_name, "w+"); if (!m4_in) error (EXIT_FAILURE, get_errno (), "fopen"); muscles_output (m4_in); fflush(m4_in); if (fseek(m4_in, 0, SEEK_SET)) error (EXIT_FAILURE, get_errno (), "fseek"); } /* Read and process m4's output. */ { m4_out = mkstempFILE(m4_out_file_name, "w+"); if (!m4_out) error (EXIT_FAILURE, get_errno (), "fopen"); } if (main_m4(i-1, argv, m4_in, m4_out)) error (EXIT_FAILURE, get_errno (), "m4 failed"); free (full_m4sugar); free (full_m4bison); free (full_skeleton); fflush(m4_out); if (fseek(m4_out, 0, SEEK_SET)) error (EXIT_FAILURE, get_errno (), "fseek"); timevar_push (TV_M4); // in = fdopen (filter_fd[0], "r"); // if (! in) // error (EXIT_FAILURE, get_errno (), // "fdopen"); scan_skel (m4_out); /* scan_skel should have read all of M4's output. Otherwise, when we close the pipe, we risk letting M4 report a broken-pipe to the Bison user. */ aver (feof (m4_out)); xfclose (m4_in); xfclose (m4_out); _unlink (m4_in_file_name); _unlink (m4_out_file_name); // wait_subprocess (pid, "m4", false, false, true, true, NULL); timevar_pop (TV_M4); }
/**************************************************************************** * Name: ubgps_handle_aid_alpsrv * * Description: * Handle AID-ALPSRV UBX message * * Input Parameters: * gps - GPS object * msg - UBX AID-ALPSRV message * * Returned Values: * Status * ****************************************************************************/ int ubgps_handle_aid_alpsrv(struct ubgps_s * const gps, struct ubx_msg_s const * const msg) { uint8_t requested_data_type; size_t data_offset; size_t data_size; ssize_t data_read; struct ubx_msg_s * resp = NULL; int alpfd = -1; int status = ERROR; int ret; DEBUGASSERT(gps && msg); if (!gps->assist) return OK; /* Check that AssistNow Offline data is available */ ret = pthread_mutex_trylock(&g_aid_mutex); if (ret != 0) { dbg_int("mutex_trylock failed: %d\n", ret); return OK; } if (!gps->assist->alp_file || !gps->assist->alp_file_id) { pthread_mutex_unlock(&g_aid_mutex); return OK; } if (!ubgps_check_alp_file_validity(gps->assist->alp_file)) { free(gps->assist->alp_file); gps->assist->alp_file = NULL; pthread_mutex_unlock(&g_aid_mutex); return OK; } requested_data_type = UBX_GET_U1(msg, 1); data_offset = (uint32_t)UBX_GET_U2(msg, 2) * 2; data_size = (uint32_t)UBX_GET_U2(msg, 4) * 2; dbg_int("file_id:%u, type:%u, offset:%u, size:%u\n", gps->assist->alp_file_id, requested_data_type, data_offset, data_size); /* Check if AID-ALPSRV is a download request */ if (requested_data_type != 0xff) { /* Allocate response */ resp = ubx_msg_allocate(UBX_CLASS_AID, UBX_AID_ALPSRV, UBX_AID_ALPSRV_LEN + data_size); if (!resp) goto errout; /* Copy original data to response */ memcpy(&resp->payload[0], &msg->payload[0], UBX_AID_ALPSRV_LEN); /* Set ALP file ID */ UBX_SET_U2(resp, 6, gps->assist->alp_file_id); } /* Open ALP file */ alpfd = open(gps->assist->alp_file, O_RDWR); if (alpfd < 0) { int error = get_errno(); dbg("ALP file '%s' open failed: %d.\n", gps->assist->alp_file, error); goto errout; } /* Seek to requested offset */ status = lseek(alpfd, data_offset, SEEK_SET); if (status < 0) { int error = get_errno(); dbg("Failed to seek ALP file to offset %d: %d.\n", data_offset, error); goto errout; } if (resp) { /* Read data from AlmanacPlus file */ data_read = read(alpfd, &resp->payload[UBX_AID_ALPSRV_LEN], data_size); if (data_read < 0) { int error = get_errno(); dbg("ALP file read failed (offset:%d, size:%d): %d.\n", data_offset, data_size, error); goto errout; } /* Set read data size */ UBX_SET_U2(resp, 8, data_read); /* Send response */ status = ubx_msg_send(gps, gps->fd, resp); } else { uint16_t file_id = UBX_GET_U2(msg, 6); /* Update data in AlmanacPlus file */ if (file_id == gps->assist->alp_file_id) { status = write(alpfd, &msg->payload[8], data_size); if (status != data_size) { status = ERROR; dbg("ALP write failed: %d\n", get_errno()); } else { status = OK; } } } errout: if (resp) UBX_MSG_FREE(resp); if (alpfd >= 0) close(alpfd); pthread_mutex_unlock(&g_aid_mutex); return status; }
static int thread_create(FAR const char *name, uint8_t ttype, int priority, int stack_size, main_t entry, FAR char * const argv[]) { FAR struct task_tcb_s *tcb; pid_t pid; int errcode; int ret; /* Allocate a TCB for the new task. */ tcb = (FAR struct task_tcb_s *)kmm_zalloc(sizeof(struct task_tcb_s)); if (!tcb) { sdbg("ERROR: Failed to allocate TCB\n"); errcode = ENOMEM; goto errout; } /* Allocate a new task group with privileges appropriate for the parent * thread type. */ #ifdef HAVE_TASK_GROUP ret = group_allocate(tcb, ttype); if (ret < 0) { errcode = -ret; goto errout_with_tcb; } #endif /* Associate file descriptors with the new task */ #if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0 ret = group_setuptaskfiles(tcb); if (ret < OK) { errcode = -ret; goto errout_with_tcb; } #endif /* Allocate the stack for the TCB */ ret = up_create_stack((FAR struct tcb_s *)tcb, stack_size, ttype); if (ret < OK) { errcode = -ret; goto errout_with_tcb; } /* Initialize the task control block */ ret = task_schedsetup(tcb, priority, task_start, entry, ttype); if (ret < OK) { errcode = EBUSY; /* No available PID */ goto errout_with_tcb; } /* Setup to pass parameters to the new task */ (void)task_argsetup(tcb, name, argv); /* Now we have enough in place that we can join the group */ #ifdef HAVE_TASK_GROUP ret = group_initialize(tcb); if (ret < 0) { errcode = -ret; goto errout_with_tcb; } #endif /* Get the assigned pid before we start the task */ pid = (int)tcb->cmn.pid; /* Activate the task */ ret = task_activate((FAR struct tcb_s *)tcb); if (ret < OK) { errcode = get_errno(); /* The TCB was added to the active task list by task_schedsetup() */ dq_rem((FAR dq_entry_t*)tcb, (dq_queue_t*)&g_inactivetasks); goto errout_with_tcb; } return pid; errout_with_tcb: sched_releasetcb((FAR struct tcb_s *)tcb, ttype); errout: set_errno(errcode); return ERROR; }
ssize_t writev(int fildes, FAR const struct iovec *iov, int iovcnt) { ssize_t ntotal; ssize_t nwritten; size_t remaining; FAR uint8_t *buffer; off_t pos; int i; /* Get the current file position in case we have to reset it */ pos = lseek(fildes, 0, SEEK_CUR); if (pos == (off_t)-1) { return ERROR; } /* Process each entry in the struct iovec array */ for (i = 0, ntotal = 0; i < iovcnt; i++) { /* Ignore zero-length writes */ if (iov[i].iov_len > 0) { buffer = iov[i].iov_base; remaining = iov[i].iov_len; /* Write repeatedly as necessary to write the entire buffer */ do { /* NOTE: write() is a cancellation point */ nwritten = write(fildes, buffer, remaining); /* Check for a write error */ if (nwritten < 0) { /* Save the errno value */ int save = get_errno(); /* Restore the file position */ (void)lseek(fildes, pos, SEEK_SET); /* Restore the errno value */ set_errno(save); return ERROR; } /* Update pointers and counts in order to handle partial * buffer writes. */ buffer += nwritten; remaining -= nwritten; ntotal += nwritten; } while (remaining > 0); } } return ntotal; }