int sigqueue(int pid, int signo, void *sival_ptr) #endif { #ifdef CONFIG_SCHED_HAVE_PARENT FAR struct tcb_s *rtcb = this_task(); #endif siginfo_t info; int ret; #ifdef CONFIG_CAN_PASS_STRUCTS sdbg("pid=0x%08x signo=%d value=%d\n", pid, signo, value.sival_int); #else sdbg("pid=0x%08x signo=%d value=%p\n", pid, signo, sival_ptr); #endif /* Sanity checks */ if (!GOOD_SIGNO(signo)) { ret = -EINVAL; goto errout; } /* Create the siginfo structure */ info.si_signo = signo; info.si_code = SI_QUEUE; info.si_errno = OK; #ifdef CONFIG_CAN_PASS_STRUCTS info.si_value = value; #else info.si_value.sival_ptr = sival_ptr; #endif #ifdef CONFIG_SCHED_HAVE_PARENT info.si_pid = rtcb->pid; info.si_status = OK; #endif /* Send the signal */ sched_lock(); ret = sig_dispatch(pid, &info); sched_unlock(); /* Check for errors */ if (ret < 0) { goto errout; } return OK; errout: set_errno(-ret); return ERROR; }
int kill(pid_t pid, int signo) { #ifdef CONFIG_SCHED_HAVE_PARENT FAR struct tcb_s *rtcb = (FAR struct tcb_s *)g_readytorun.head; #endif siginfo_t info; int ret; /* We do not support sending signals to process groups */ if (pid <= 0) { ret = -ENOSYS; goto errout; } /* Make sure that the signal is valid */ if (!GOOD_SIGNO(signo)) { ret = -EINVAL; goto errout; } /* Keep things stationary through the following */ sched_lock(); /* Create the siginfo structure */ info.si_signo = signo; info.si_code = SI_USER; info.si_errno = EINTR; info.si_value.sival_ptr = NULL; #ifdef CONFIG_SCHED_HAVE_PARENT info.si_pid = rtcb->pid; info.si_status = OK; #endif /* Send the signal */ ret = sig_dispatch(pid, &info); sched_unlock(); if (ret < 0) { goto errout; } return OK; errout: set_errno(-ret); return ERROR; }
_sa_handler_t signal(int signo, _sa_handler_t func) { struct sigaction act; struct sigaction oact; int ret; DEBUGASSERT(GOOD_SIGNO(signo) && func != SIG_ERR && func != SIG_HOLD); /* Initialize the sigaction structure */ act.sa_handler = func; act.sa_flags = 0; (void)sigemptyset(&act.sa_mask); /* Check for SIG_IGN and SIG_DFL (and someday SIG_HOLD) * * REVISIT: Currently SIG_IGN, SIG_DFL, and SIG_HOLD have the same value * and cannot be distinguished. */ if (func != SIG_DFL /* && func != SIG_IGN */) { /* Add the signal to the set of signals to be ignored when the signal * handler executes. */ ret = sigaddset(&act.sa_mask, signo); if (ret < 0) { /* Would happen if signo were invalid */ return (_sa_handler_t)SIG_ERR; } } /* Set the signal disposition */ ret = sigaction(signo, &act, &oact); /* Upon successful completion, signal() will the signal's previous * disposition. Otherwise, SIG_ERR will be returned and errno set to * indicate the error. */ if (ret == OK) { return oact.sa_handler; } return (_sa_handler_t)SIG_ERR; }
int sigdelset(FAR sigset_t *set, int signo) { int ret = ERROR; /* Verify the signal */ if (GOOD_SIGNO(signo)) { /* Delete the signal to the set */ *set &= ~SIGNO2SET(signo); ret = OK; } return ret; }
int sigismember(FAR const sigset_t *set, int signo) { int ret = ERROR; /* Verify the signal */ if (GOOD_SIGNO(signo)) { /* Check if the signal is in the set */ ret = ((*set & SIGNO2SET(signo)) != 0); } return ret; }
int sigaddset(FAR sigset_t *set, int signo) { int ret = ERROR; /* Verify the signal */ if (GOOD_SIGNO(signo)) { /* Add the signal to the set */ *set |= SIGNO2SET(signo); ret = OK; } return ret; }
int sigaddset(FAR sigset_t *set, int signo) { /* Verify the signal */ if (!GOOD_SIGNO(signo)) { set_errno(EINVAL); return ERROR; } else { /* Add the signal to the set */ *set |= SIGNO2SET(signo); return OK; } }
CODE void (*sigset(int signo, CODE void (*func)(int signo)))(int signo) { _sa_handler_t disposition; sigset_t set; int ret; DEBUGASSERT(GOOD_SIGNO(signo) && func != SIG_ERR); (void)sigemptyset(&set); (void)sigaddset(&set, signo); /* Check if we are being asked to block the signal */ if (func == SIG_HOLD) { ret = sigprocmask(SIG_BLOCK, &set, NULL); disposition = ret < 0 ? SIG_ERR : SIG_HOLD; } /* No.. then signal can handle the other cases */ else { /* Set the signal handler disposition */ disposition = signal(signo, func); if (disposition != SIG_ERR) { /* And unblock the signal */ ret = sigprocmask(SIG_UNBLOCK, &set, NULL); if (ret < 0) { /* Restore the original signal disposition and return and * error. */ (void)signal(signo, disposition); disposition = SIG_ERR; } } } return disposition; }
int sig_mqnotempty(int pid, int signo, void *sival_ptr) #endif { #ifdef CONFIG_SCHED_HAVE_PARENT FAR struct tcb_s *rtcb = (FAR struct tcb_s *)g_readytorun.head; #endif siginfo_t info; int ret; #ifdef CONFIG_CAN_PASS_STRUCTS sdbg("pid=%p signo=%d value=%d\n", pid, signo, value.sival_int); #else sdbg("pid=%p signo=%d sival_ptr=%p\n", pid, signo, sival_ptr); #endif /* Verify that we can perform the signalling operation */ if (!GOOD_SIGNO(signo)) { return -EINVAL; } /* Create the siginfo structure */ info.si_signo = signo; info.si_code = SI_MESGQ; #ifdef CONFIG_CAN_PASS_STRUCTS info.si_value = value; #else info.si_value.sival_ptr = sival_ptr; #endif #ifdef CONFIG_SCHED_HAVE_PARENT info.si_pid = rtcb->pid; info.si_status = OK; #endif /* Process the receipt of the signal */ sched_lock(); ret = sig_dispatch(pid, &info); sched_unlock(); return ret; }
int sig_mqnotempty (int pid, int signo, void *sival_ptr) #endif { FAR _TCB *stcb; siginfo_t info; int ret = ERROR; sched_lock(); /* Get the TCB of the receiving task */ stcb = sched_gettcb(pid); #ifdef CONFIG_CAN_PASS_STRUCTS sdbg("TCB=%p signo=%d value=%d\n", stcb, signo, value.sival_int); #else sdbg("TCB=%p signo=%d sival_ptr=%p\n", stcb, signo, sival_ptr); #endif /* Create the siginfo structure */ info.si_signo = signo; info.si_code = SI_MESGQ; #ifdef CONFIG_CAN_PASS_STRUCTS info.si_value = value; #else info.si_value.sival_ptr = sival_ptr; #endif /* Verify that we can perform the signalling operation */ if ((stcb) && (GOOD_SIGNO(signo))) { /* Process the receipt of the signal */ ret = sig_received(stcb, &info); } sched_unlock(); return ret; }
static void ft80x_notify(FAR struct ft80x_dev_s *priv, enum ft80x_notify_e event, int arg) { FAR struct ft80x_eventinfo_s *info = &priv->notify[event]; #ifdef CONFIG_CAN_PASS_STRUCTS union sigval value; #endif /* Are notifications enabled for this event? */ if (info->enable) { DEBUGASSERT(info->signo > 0 && GOOD_SIGNO(info->signo) && info->pid > 0); /* Yes.. Signal the client */ #ifdef CONFIG_CAN_PASS_STRUCTS value.sival_int = arg; (void)nxsig_queue(info->pid, info->signo, value); #else (void)nxsig_queue(info->pid, info->signo, (FAR void *)arg); #endif } }
static int ft80x_ioctl(FAR struct file *filep, int cmd, unsigned long arg) { FAR struct inode *inode; FAR struct ft80x_dev_s *priv; int ret; DEBUGASSERT(filep != NULL); inode = filep->f_inode; DEBUGASSERT(inode != NULL && inode->i_private != NULL); priv = inode->i_private; lcdinfo("cmd: %d arg: %lu\n", cmd, arg); /* Get exclusive access to the device structures */ ret = nxsem_wait(&priv->exclsem); if (ret < 0) { return ret; } /* Handle built-in ioctl commands */ switch (cmd) { /* FT80X_IOC_CREATEDL: * Description: Write a display list to the FT80x display list memory * Description: Write a display list to the FT80x display list memory * starting at offset zero. This may or may not be the * entire display list. Display lists may be created * incrementally, starting with FT80X_IOC_CREATEDL and * finishing the display list using FT80XIO_APPENDDL * Argument: A reference to a display list structure instance. * See struct ft80x_displaylist_s. * Returns: None */ case FT80X_IOC_CREATEDL: /* Set the file position to zero and fall through to "append" the new * display list data at offset 0. */ filep->f_pos = 0; /* FALLTHROUGH */ /* FT80X_IOC_APPENDDL: * Description: Write additional display list entries to the FT80x * display list memory at the current display list offset. * This IOCTL command permits display lists to be completed * incrementally, starting with FT80X_IOC_CREATEDL and * finishing the display list using FT80XIO_APPENDDL. * Argument: A reference to a display list structure instance. See * struct ft80x_displaylist_s. * Returns: None */ case FT80X_IOC_APPENDDL: { FAR struct ft80x_displaylist_s *dl = (FAR struct ft80x_displaylist_s *)((uintptr_t)arg); if (dl == NULL || ((uintptr_t)&dl->cmd & 3) != 0 || (dl->dlsize & 3) != 0 || dl->dlsize + filep->f_pos > FT80X_RAM_DL_SIZE) { ret = -EINVAL; } else { /* Check if there is a display list. It might be useful for * the application to issue FT80X_IOC_CREATEDL with no data in * order to initialize the display list, then form all of the * list entries with FT80X_IOC_APPENDDL. */ if (dl->dlsize > 0) { /* This IOCTL command simply copies the display list * provided into the FT80x display list memory. */ ft80x_write_memory(priv, FT80X_RAM_DL + filep->f_pos, &dl->cmd, dl->dlsize); filep->f_pos += dl->dlsize; } ret = OK; } } break; /* FT80X_IOC_GETRAMDL: * Description: Read a 32-bit value from the display list. * Argument: A reference to an instance of struct ft80x_relmem_s. * Returns: The 32-bit value read from the display list. */ case FT80X_IOC_GETRAMDL: { FAR struct ft80x_relmem_s *ramdl = (FAR struct ft80x_relmem_s *)((uintptr_t)arg); if (ramdl == NULL || ((uintptr_t)ramdl->offset & 3) != 0 || ramdl->offset >= FT80X_RAM_DL_SIZE) { ret = -EINVAL; } else { ft80x_read_memory(priv, FT80X_RAM_DL + ramdl->offset, ramdl->value, ramdl->nbytes); ret = OK; } } break; /* FT80X_IOC_PUTRAMG * Description: Write byte data to FT80x graphics memory (RAM_G) * Argument: A reference to an instance of struct ft80x_relmem_s. * Returns: None. */ case FT80X_IOC_PUTRAMG: { FAR struct ft80x_relmem_s *ramg = (FAR struct ft80x_relmem_s *)((uintptr_t)arg); if (ramg == NULL || (ramg->offset + ramg->nbytes) >= FT80X_RAM_G_SIZE) { ret = -EINVAL; } else { ft80x_write_memory(priv, FT80X_RAM_G + ramg->offset, ramg->value, ramg->nbytes); ret = OK; } } break; /* FT80X_IOC_PUTRAMCMD * Description: Write 32-bit aligned data to FT80x FIFO (RAM_CMD) * Argument: A reference to an instance of struct ft80x_relmem_s below. * Returns: None. */ case FT80X_IOC_PUTRAMCMD: { FAR struct ft80x_relmem_s *ramcmd = (FAR struct ft80x_relmem_s *)((uintptr_t)arg); if (ramcmd == NULL || ((uintptr_t)ramcmd->offset & 3) != 0 /* || ramcmd->offset >= FT80X_CMDFIFO_SIZE */ ) { ret = -EINVAL; } else { ft80x_write_memory(priv, FT80X_RAM_CMD + ramcmd->offset, ramcmd->value, ramcmd->nbytes); ret = OK; } } break; /* FT80X_IOC_GETREG8: * Description: Read an 8-bit register value from the FT80x. * Argument: A reference to an instance of struct ft80x_register_s. * Returns: The 8-bit value read from the register. */ case FT80X_IOC_GETREG8: { FAR struct ft80x_register_s *reg = (FAR struct ft80x_register_s *)((uintptr_t)arg); if (reg == NULL || ((uintptr_t)reg->addr & 3) != 0) { ret = -EINVAL; } else { reg->value.u8 = ft80x_read_byte(priv, reg->addr); ret = OK; } } break; /* FT80X_IOC_GETREG16: * Description: Read a 16-bit register value from the FT80x. * Argument: A reference to an instance of struct ft80x_register_s. * Returns: The 16-bit value read from the register. */ case FT80X_IOC_GETREG16: { FAR struct ft80x_register_s *reg = (FAR struct ft80x_register_s *)((uintptr_t)arg); if (reg == NULL || ((uintptr_t)reg->addr & 3) != 0) { ret = -EINVAL; } else { reg->value.u16 = ft80x_read_hword(priv, reg->addr); ret = OK; } } break; /* FT80X_IOC_GETREG32: * Description: Read a 32-bit register value from the FT80x. * Argument: A reference to an instance of struct ft80x_register_s. * Returns: The 32-bit value read from the register. */ case FT80X_IOC_GETREG32: { FAR struct ft80x_register_s *reg = (FAR struct ft80x_register_s *)((uintptr_t)arg); if (reg == NULL || ((uintptr_t)reg->addr & 3) != 0) { ret = -EINVAL; } else { reg->value.u32 = ft80x_read_word(priv, reg->addr); ret = OK; } } break; /* FT80X_IOC_GETREGS: * Description: Read multiple 32-bit register values from the FT80x. * Argument: A reference to an instance of struct ft80x_registers_s. * Returns: The 32-bit values read from the consecutive registers . */ case FT80X_IOC_GETREGS: { FAR struct ft80x_registers_s *regs = (FAR struct ft80x_registers_s *)((uintptr_t)arg); if (regs == NULL || ((uintptr_t)regs->addr & 3) != 0) { ret = -EINVAL; } else { ft80x_read_memory(priv, regs->addr, regs->value, (size_t)regs->nregs << 2); ret = OK; } } break; /* FT80X_IOC_PUTREG8: * Description: Write an 8-bit register value to the FT80x. * Argument: A reference to an instance of struct ft80x_register_s. * Returns: None. */ case FT80X_IOC_PUTREG8: { FAR struct ft80x_register_s *reg = (FAR struct ft80x_register_s *)((uintptr_t)arg); if (reg == NULL || ((uintptr_t)reg->addr & 3) != 0) { ret = -EINVAL; } else { ft80x_write_byte(priv, reg->addr, reg->value.u8); ret = OK; } } break; /* FT80X_IOC_PUTREG16: * Description: Write a 16-bit register value to the FT80x. * Argument: A reference to an instance of struct ft80x_register_s. * Returns: None. */ case FT80X_IOC_PUTREG16: { FAR struct ft80x_register_s *reg = (FAR struct ft80x_register_s *)((uintptr_t)arg); if (reg == NULL || ((uintptr_t)reg->addr & 3) != 0) { ret = -EINVAL; } else { ft80x_write_hword(priv, reg->addr, reg->value.u16); ret = OK; } } break; /* FT80X_IOC_PUTREG32: * Description: Write a 32-bit register value to the FT80x. * Argument: A reference to an instance of struct ft80x_register_s. * Returns: None. */ case FT80X_IOC_PUTREG32: { FAR struct ft80x_register_s *reg = (FAR struct ft80x_register_s *)((uintptr_t)arg); if (reg == NULL || ((uintptr_t)reg->addr & 3) != 0) { ret = -EINVAL; } else { ft80x_write_word(priv, reg->addr, reg->value.u32); ret = OK; } } break; /* FT80X_IOC_PUTREGS: * Description: Write multiple 32-bit register values to the FT80x. * Argument: A reference to an instance of struct ft80x_registers_s. * Returns: None. */ case FT80X_IOC_PUTREGS: { FAR struct ft80x_registers_s *regs = (FAR struct ft80x_registers_s *)((uintptr_t)arg); if (regs == NULL || ((uintptr_t)regs->addr & 3) != 0) { ret = -EINVAL; } else { ft80x_write_memory(priv, regs->addr, regs->value, (size_t)regs->nregs << 2); ret = OK; } } break; /* FT80X_IOC_EVENTNOTIFY: * Description: Setup to receive a signal when an event occurs. * Argument: A reference to an instance of struct ft80x_notify_s. * Returns: None */ case FT80X_IOC_EVENTNOTIFY: { FAR struct ft80x_notify_s *notify = (FAR struct ft80x_notify_s *)((uintptr_t)arg); if (notify == NULL || !GOOD_SIGNO(notify->signo) || notify->pid < 0 || (unsigned int)notify->event >= FT80X_INT_NEVENTS) { ret = -EINVAL; } else { FAR struct ft80x_eventinfo_s *info = &priv->notify[notify->event]; uint32_t regval; /* Are we enabling or disabling */ if (notify->enable) { /* Make sure that arguments are valid for the enable */ if (notify->signo == 0 || notify->pid == 0) { ret = -EINVAL; } else { /* Setup the new notification information */ info->signo = notify->signo; info->pid = notify->pid; info->enable = true; /* Enable interrupts associated with the event */ regval = ft80x_read_word(priv, FT80X_REG_INT_MASK); regval |= (1 << notify->event); ft80x_write_word(priv, FT80X_REG_INT_MASK, regval); ret = OK; } } else { /* Disable the notification */ info->signo = 0; info->pid = 0; info->enable = false; /* Disable interrupts associated with the event */ regval = ft80x_read_word(priv, FT80X_REG_INT_MASK); regval &= ~(1 << notify->event); ft80x_write_word(priv, FT80X_REG_INT_MASK, regval); ret = OK; } } } break; /* FT80X_IOC_FADE: * Description: Change the backlight intensity with a controllable * fade. * Argument: A reference to an instance of struct ft80x_fade_s. * Returns: None. */ case FT80X_IOC_FADE: { FAR const struct ft80x_fade_s *fade = (FAR const struct ft80x_fade_s *)((uintptr_t)arg); if (fade == NULL || fade->duty > 100 || fade->delay < MIN_FADE_DELAY || fade->delay > MAX_FADE_DELAY) { ret = -EINVAL; } else { ret = ft80x_fade(priv, fade); } } break; /* FT80X_IOC_AUDIO: * Description: Enable/disable an external audio amplifer. * Argument: 0=disable; 1=enable. * Returns: None. */ case FT80X_IOC_AUDIO: { #if defined(CONFIG_LCD_FT80X_AUDIO_MCUSHUTDOWN) /* Amplifier is controlled by an MCU GPIO pin */ DEBUGASSERT(priv->lower->attach != NULL && priv->lower->audio != NULL); DEBUGASSERT(arg == 0 || arg == 1); priv->lower->audio(priv->lower, (arg != 0)); ret = OK; #elif defined(CONFIG_LCD_FT80X_AUDIO_GPIOSHUTDOWN) /* Amplifier is controlled by an FT80x GPIO pin */ uint8_t regval8; DEBUGASSERT(arg == 0 || arg == 1); regval8 = ft80x_read_byte(priv, FT80X_REG_GPIO); /* Active low logic assumed */ if (arg == 0) { regval8 |= (1 << CONFIG_LCD_FT80X_AUDIO_GPIO); } else { regval8 &= ~(1 << CONFIG_LCD_FT80X_AUDIO_GPIO); } ft80x_write_byte(priv, FT80X_REG_GPIO, regval8); ret = OK; #else /* Amplifier is not controllable. */ DEBUGASSERT(arg == 0 || arg == 1); return OK; #endif } break; /* Unrecognized IOCTL command */ default: lcderr("ERROR: Unrecognized cmd: %d arg: %ld\n", cmd, arg); ret = -ENOTTY; break; } nxsem_post(&priv->exclsem); return ret; }
int sigtimedwait(FAR const sigset_t *set, FAR struct siginfo *info, FAR const struct timespec *timeout) { FAR struct tcb_s *rtcb = (FAR struct tcb_s*)g_readytorun.head; sigset_t intersection; FAR sigpendq_t *sigpend; irqstate_t saved_state; int32_t waitticks; int ret = ERROR; DEBUGASSERT(rtcb->waitdog == NULL); sched_lock(); /* Not necessary */ /* Several operations must be performed below: We must determine if any * signal is pending and, if not, wait for the signal. Since signals can * be posted from the interrupt level, there is a race condition that * can only be eliminated by disabling interrupts! */ saved_state = irqsave(); /* Check if there is a pending signal corresponding to one of the * signals in the pending signal set argument. */ intersection = *set & sig_pendingset(rtcb); if (intersection != NULL_SIGNAL_SET) { /* One or more of the signals in intersections is sufficient to cause * us to not wait. Pick the lowest numbered signal and mark it not * pending. */ sigpend = sig_removependingsignal(rtcb, sig_lowest(&intersection)); ASSERT(sigpend); /* Return the signal info to the caller if so requested */ if (info) { memcpy(info, &sigpend->info, sizeof(struct siginfo)); } /* Then dispose of the pending signal structure properly */ sig_releasependingsignal(sigpend); irqrestore(saved_state); /* The return value is the number of the signal that awakened us */ ret = sigpend->info.si_signo; } /* We will have to wait for a signal to be posted to this task. */ else { /* Save the set of pending signals to wait for */ rtcb->sigwaitmask = *set; /* Check if we should wait for the timeout */ if (timeout) { /* Convert the timespec to system clock ticks, making sure that * the resulting delay is greater than or equal to the requested * time in nanoseconds. */ #ifdef CONFIG_HAVE_LONG_LONG uint64_t waitticks64 = ((uint64_t)timeout->tv_sec * NSEC_PER_SEC + (uint64_t)timeout->tv_nsec + NSEC_PER_TICK - 1) / NSEC_PER_TICK; DEBUGASSERT(waitticks64 <= UINT32_MAX); waitticks = (uint32_t)waitticks64; #else uint32_t waitmsec; DEBUGASSERT(timeout->tv_sec < UINT32_MAX / MSEC_PER_SEC); waitmsec = timeout->tv_sec * MSEC_PER_SEC + (timeout->tv_nsec + NSEC_PER_MSEC - 1) / NSEC_PER_MSEC; waitticks = MSEC2TICK(waitmsec); #endif /* Create a watchdog */ rtcb->waitdog = wd_create(); DEBUGASSERT(rtcb->waitdog); if (rtcb->waitdog) { /* This little bit of nonsense is necessary for some * processors where sizeof(pointer) < sizeof(uint32_t). * see wdog.h. */ wdparm_t wdparm; wdparm.pvarg = (FAR void *)rtcb; /* Start the watchdog */ wd_start(rtcb->waitdog, waitticks, (wdentry_t)sig_timeout, 1, wdparm.dwarg); /* Now wait for either the signal or the watchdog */ up_block_task(rtcb, TSTATE_WAIT_SIG); /* We no longer need the watchdog */ wd_delete(rtcb->waitdog); rtcb->waitdog = NULL; } /* REVISIT: And do what if there are no watchdog timers? The wait * will fail and we will return something bogus. */ } /* No timeout, just wait */ else { /* And wait until one of the unblocked signals is posted */ up_block_task(rtcb, TSTATE_WAIT_SIG); } /* We are running again, clear the sigwaitmask */ rtcb->sigwaitmask = NULL_SIGNAL_SET; /* When we awaken, the cause will be in the TCB. Get the signal number * or timeout) that awakened us. */ if (GOOD_SIGNO(rtcb->sigunbinfo.si_signo)) { /* We were awakened by a signal... but is it one of the signals that * we were waiting for? */ if (sigismember(set, rtcb->sigunbinfo.si_signo)) { /* Yes.. the return value is the number of the signal that * awakened us. */ ret = rtcb->sigunbinfo.si_signo; } else { /* No... then set EINTR and report an error */ set_errno(EINTR); ret = ERROR; } } else { /* Otherwise, we must have been awakened by the timeout. Set EGAIN * and return an error. */ DEBUGASSERT(rtcb->sigunbinfo.si_signo == SIG_WAIT_TIMEOUT); set_errno(EAGAIN); ret = ERROR; } /* Return the signal info to the caller if so requested */ if (info) { memcpy(info, &rtcb->sigunbinfo, sizeof(struct siginfo)); } irqrestore(saved_state); } sched_unlock(); return ret; }
int pthread_kill(pthread_t thread, int signo) { #ifdef HAVE_GROUP_MEMBERS /* If group members are support then pthread_kill() differs from kill(). * kill(), in this case, must following the POSIX rules for delivery of * signals in the group environment. Otherwise, kill(), like * pthread_kill() will just deliver the signal to the thread ID it is * requested to use. */ #ifdef CONFIG_SCHED_HAVE_PARENT FAR struct tcb_s *rtcb = (FAR struct tcb_s *)g_readytorun.head; #endif FAR struct tcb_s *stcb; siginfo_t info; int ret; /* Make sure that the signal is valid */ if (!GOOD_SIGNO(signo)) { ret = -EINVAL; goto errout; } /* Keep things stationary through the following */ sched_lock(); /* Create the siginfo structure */ info.si_signo = signo; info.si_code = SI_USER; info.si_value.sival_ptr = NULL; #ifdef CONFIG_SCHED_HAVE_PARENT info.si_pid = rtcb->pid; info.si_status = OK; #endif /* Get the TCB associated with the thread */ stcb = sched_gettcb((pid_t)thread); if (!stcb) { ret = -ESRCH; goto errout_with_lock; } /* Dispatch the signal to thread, bypassing normal task group thread * dispatch rules. */ ret = sig_tcbdispatch(stcb, &info); sched_unlock(); if (ret < 0) { goto errout; } return OK; errout_with_lock: sched_unlock(); errout: return -ret; #else /* If group members are not supported then pthread_kill is basically the * same as kill(). */ int ret; set_errno(EINVAL); ret = kill((pid_t)thread, signo); if (ret != OK) { ret = get_errno(); } return ret; #endif }
int sigaction(int signo, FAR const struct sigaction *act, FAR struct sigaction *oact) { FAR struct tcb_s *rtcb = (FAR struct tcb_s*)g_readytorun.head; FAR sigactq_t *sigact; /* Since sigactions can only be installed from the running thread of * execution, no special precautions should be necessary. */ /* Verify the signal number */ if (!GOOD_SIGNO(signo)) { set_errno(EINVAL); return ERROR; } /* Find the signal in the sigactionq */ sigact = sig_findaction(rtcb, signo); /* Return the old sigaction value if so requested */ if (oact) { if (sigact) { COPY_SIGACTION(oact, &sigact->act); } else { /* There isn't an old value */ oact->sa_u._sa_handler = NULL; oact->sa_mask = NULL_SIGNAL_SET; oact->sa_flags = 0; } } /* If the argument act is a null pointer, signal handling is unchanged; * thus, the call can be used to enquire about the current handling of * a given signal. */ if (!act) { return OK; } #if defined(CONFIG_SCHED_HAVE_PARENT) && defined(CONFIG_SCHED_CHILD_STATUS) /* Handle a special case. Retention of child status can be suppressed * if signo == SIGCHLD and sa_flags == SA_NOCLDWAIT. * * POSIX.1 leaves it unspecified whether a SIGCHLD signal is generated * when a child process terminates. In NuttX, a SIGCHLD signal is * generated in this case; but in some other implementations, it may not * be. */ if (signo == SIGCHLD && (act->sa_flags & SA_NOCLDWAIT) != 0) { irqstate_t flags; /* We do require a critical section to muck with the TCB values that * can be modified by the child thread. */ flags = irqsave(); /* Mark that status should be not be retained */ rtcb->group->tg_flags |= GROUP_FLAG_NOCLDWAIT; /* Free all pending exit status */ group_removechildren(rtcb->group); irqrestore(flags); } #endif /* Handle the case where no sigaction is supplied (SIG_IGN) */ if (act->sa_u._sa_handler == SIG_IGN) { /* Do we still have a sigaction container from the previous setting? */ if (sigact) { /* Yes.. Remove it from sigactionq */ sq_rem((FAR sq_entry_t*)sigact, &rtcb->sigactionq); /* And deallocate it */ sig_releaseaction(sigact); } } /* A sigaction has been supplied */ else { /* Do we still have a sigaction container from the previous setting? * If so, then re-use for the new signal action. */ if (!sigact) { /* No.. Then we need to allocate one for the new action. */ sigact = sig_allocateaction(); /* An error has occurred if we could not allocate the sigaction */ if (!sigact) { set_errno(ENOMEM); return ERROR; } /* Put the signal number in the queue entry */ sigact->signo = (uint8_t)signo; /* Add the new sigaction to sigactionq */ sq_addlast((FAR sq_entry_t*)sigact, &rtcb->sigactionq); } /* Set the new sigaction */ COPY_SIGACTION(&sigact->act, act); } return OK; }
FAR char *strsignal(int signum) { /* Handle invalid signals */ if (!GOOD_SIGNO(signum)) { return (FAR char *)"Invalid Signal"; } /* Handle named signals */ switch (signum) { /* Standard signals */ #ifdef SIGUSR1 case SIGUSR1: return (FAR char *)"SIGUSR1"; #endif #ifdef SIGUSR2 case SIGUSR2: return (FAR char *)"SIGUSR2"; #endif #ifdef SIGALRM case SIGALRM: return (FAR char *)"SIGALRM"; #endif #ifdef SIGCHLD case SIGCHLD: return (FAR char *)"SIGCHLD"; #endif #ifdef SIGPOLL case SIGPOLL: return (FAR char *)"SIGPOLL"; #endif #ifdef SIGSTOP case SIGSTOP: return (FAR char *)"SIGSTOP"; #endif #ifdef SIGSTP case SIGSTP: return (FAR char *)"SIGSTP"; #endif #ifdef SIGCONT case SIGCONT: return (FAR char *)"SIGCONT"; #endif #ifdef SIGKILL case SIGKILL: return (FAR char *)"SIGKILL"; #endif #ifdef SIGINT case SIGINT: return (FAR char *)"SIGINT"; #endif /* Non-standard signals */ #ifdef SIGCONDTIMEDOUT case SIGCONDTIMEDOUT: return (FAR char *)"SIGCONDTIMEDOUT"; #endif #ifdef SIGWORK case SIGWORK: return (FAR char *)"SIGWORK"; #endif default: break; } /* Return a string devoid is meaning */ return (FAR char *)g_default_sigstr[signum]; }
int sigaction(int signo, FAR const struct sigaction *act, FAR struct sigaction *oact) { FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; FAR sigactq_t *sigact; int ret = ERROR; /* Assume failure */ /* Since sigactions can only be installed from the running thread of * execution, no special precautions should be necessary. */ /* Verify the signal */ if (GOOD_SIGNO(signo)) { ret = OK; /* Assume success */ /* Find the signal in the sigactionq */ sigact = sig_findaction(rtcb, signo); /* Return the old sigaction value if so requested */ if (oact) { if (sigact) { COPY_SIGACTION(oact, &sigact->act); } else { /* There isn't an old value */ oact->sa_u._sa_handler = NULL; oact->sa_mask = NULL_SIGNAL_SET; oact->sa_flags = 0; } } /* If no sigaction was found, but one is needed, then * allocate one. */ if (!sigact && act && act->sa_u._sa_handler) { sigact = sig_allocateaction(); /* An error has occurred if we could not allocate the sigaction */ if (!sigact) { ret = ERROR; } else { /* Put the signal number in the queue entry */ sigact->signo = (uint8_t)signo; /* Add the new sigaction to sigactionq */ sq_addlast((FAR sq_entry_t*)sigact, &rtcb->sigactionq); } } /* Set the new sigaction if so requested */ if ((sigact) && (act)) { /* Check if it is a request to install a new handler */ if (act->sa_u._sa_handler) { COPY_SIGACTION(&sigact->act, act); } /* No.. It is a request to remove the old handler */ else { /* Remove the old sigaction from sigactionq */ sq_rem((FAR sq_entry_t*)sigact, &rtcb->sigactionq); /* And deallocate it */ sig_releaseaction(sigact); } } } return ret; }