mirror of
https://github.com/apache/nuttx.git
synced 2026-06-04 14:53:47 +08:00
This commit adds support for default signal actions for SIGSTOP, SIGSTP, and SIGCONT.
Squashed commit of the following:
Add procfs support to show stopped tasks. Add nxsig_action() to solve a chicken and egg problem: We needed to use sigaction to set default actions, but sigaction() would refuse to set actions if the default actions could not be caught or ignored.
sched/signal: Add configuration option to selectively enabled/disable default signal actions for SIGSTOP/SIGSTP/SIGCONT and SIGKILL/SIGINT. Fix some compilation issues.
sched/sched: Okay.. I figured out a way to handle state changes that may occur while they were stopped. If a task/thread was already blocked when SIGSTOP/SIGSTP was received, it will restart in the running state. I will appear that to the task/thread that the blocked condition was interrupt by a signal and returns the EINTR error.
sched/group and sched/sched: Finish framework for continue/resume logic.
sched/signal: Roughing out basic structure to support task suspend/resume
This commit is contained in:
@@ -4874,10 +4874,63 @@ interface of the same name.
|
|||||||
The signal handler is a user-supplied function that is bound to a specific signal and performs whatever actions are necessary whenever the signal is received.
|
The signal handler is a user-supplied function that is bound to a specific signal and performs whatever actions are necessary whenever the signal is received.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
There are no predefined actions for any signal.
|
By default, here are no predefined actions for any signal.
|
||||||
The default action for all signals (i.e., when no signal handler has been supplied by the user) is to ignore the signal.
|
The default action for all signals (i.e., when no signal handler has been supplied by the user) is to ignore the signal.
|
||||||
In this sense, all NuttX are <i>real time</i> signals.
|
In this sense, all NuttX are <i>real time</i> signals by default.
|
||||||
|
If the configuration option <code>CONFIG_SIG_DEFAULT=y</code> is included, some signals will perform their default actions dependent upon addition configuration settings as summarized in the following table:
|
||||||
</p>
|
</p>
|
||||||
|
<p><ul><table>
|
||||||
|
<tr>
|
||||||
|
<th>Signal</th>
|
||||||
|
<th>Action</th>
|
||||||
|
<th>Additional Configuration</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>SIGUSR1</code></td>
|
||||||
|
<td>Abnormal Termination</td>
|
||||||
|
<td><code>CONFIG_SIG_SIGUSR1_ACTION</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>SIGUSR2</code></td>
|
||||||
|
<td>Abnormal Termination</td>
|
||||||
|
<td><code>CONFIG_SIG_SIGUSR2_ACTION</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>SIGALRM</code></td>
|
||||||
|
<td>Abnormal Termination</td>
|
||||||
|
<td><code>CONFIG_SIG_SIGALRM_ACTION</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>SIGPOLL</code></td>
|
||||||
|
<td>Abnormal Termination</td>
|
||||||
|
<td><code>CONFIG_SIG_SIGPOLL_ACTION</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>SIGSTOP</code></td>
|
||||||
|
<td>Suspend task</td>
|
||||||
|
<td><code>CONFIG_SIG_SIGSTOP_ACTION</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>SIGSTP</code></td>
|
||||||
|
<td>Suspend task</td>
|
||||||
|
<td><code>CONFIG_SIG_SIGSTOP_ACTION</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>SIGCONT</code></td>
|
||||||
|
<td>Resume task</td>
|
||||||
|
<td><code>CONFIG_SIG_SIGSTOP_ACTION</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>SIGINT</code></td>
|
||||||
|
<td>Abnormal Termination</td>
|
||||||
|
<td><code>CONFIG_SIG_SIGKILL_ACTION</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>SIGKILL</code></td>
|
||||||
|
<td>Abnormal Termination</td>
|
||||||
|
<td><code>CONFIG_SIG_SIGKILL_ACTION</code></td>
|
||||||
|
</tr>
|
||||||
|
</table></ul></p>
|
||||||
<p>
|
<p>
|
||||||
Tasks may also suspend themselves and wait until a signal is received.
|
Tasks may also suspend themselves and wait until a signal is received.
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
NuttX TODO List (Last updated August 26, 2018)
|
NuttX TODO List (Last updated August 30, 2018)
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
This file summarizes known NuttX bugs, limitations, inconsistencies with
|
This file summarizes known NuttX bugs, limitations, inconsistencies with
|
||||||
@@ -579,10 +579,24 @@ o Signals (sched/signal, arch/)
|
|||||||
^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
Title: STANDARD SIGNALS
|
Title: STANDARD SIGNALS
|
||||||
Description: 'Standard' signals and signal actions are not supported.
|
Description: 'Standard' signals and signal actions are not fully
|
||||||
(e.g., SIGINT, SIGSEGV, etc). Default is only SIG_IGN.
|
supported. The SIGCHLD signal is supported and, if the
|
||||||
|
option CONFIG_SIG_DEFAULT=y is included, some signals will
|
||||||
|
perform their default actions (dependent upon addition
|
||||||
|
configuration settings):
|
||||||
|
|
||||||
|
Signal Action Additional Configuration
|
||||||
|
------- -------------------- -------------------------
|
||||||
|
SIGUSR1 Abnormal Termination CONFIG_SIG_SIGUSR1_ACTION
|
||||||
|
SIGUSR2 Abnormal Termination CONFIG_SIG_SIGUSR2_ACTION
|
||||||
|
SIGALRM Abnormal Termination CONFIG_SIG_SIGALRM_ACTION
|
||||||
|
SIGPOLL Abnormal Termination CONFIG_SIG_SIGPOLL_ACTION
|
||||||
|
SIGSTOP Suspend task CONFIG_SIG_SIGSTOP_ACTION
|
||||||
|
SIGSTP Suspend task CONFIG_SIG_SIGSTOP_ACTION
|
||||||
|
SIGCONT Resume task CONFIG_SIG_SIGSTOP_ACTION
|
||||||
|
SIGINT Abnormal Termination CONFIG_SIG_SIGKILL_ACTION
|
||||||
|
SIGKILL Abnormal Termination CONFIG_SIG_SIGKILL_ACTION
|
||||||
|
|
||||||
Update: SIGCHLD is supported if so configured.
|
|
||||||
Status: Open. No further changes are planned.
|
Status: Open. No further changes are planned.
|
||||||
Priority: Low, required by standards but not so critical for an
|
Priority: Low, required by standards but not so critical for an
|
||||||
embedded system.
|
embedded system.
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ config SERIAL_TERMIOS
|
|||||||
config TTY_SIGINT
|
config TTY_SIGINT
|
||||||
bool "Support SIGINT"
|
bool "Support SIGINT"
|
||||||
default n
|
default n
|
||||||
select SIG_DEFAULT
|
select SIG_SIGKILL_ACTION
|
||||||
depends on !DISABLE_SIGNALS && SERIAL_TERMIOS
|
depends on !DISABLE_SIGNALS && SERIAL_TERMIOS
|
||||||
---help---
|
---help---
|
||||||
Whether support Ctrl-c/x event. Enabled automatically for console
|
Whether support Ctrl-c/x event. Enabled automatically for console
|
||||||
|
|||||||
@@ -359,13 +359,16 @@ static FAR const char *g_statenames[] =
|
|||||||
#endif
|
#endif
|
||||||
"Running",
|
"Running",
|
||||||
"Inactive",
|
"Inactive",
|
||||||
"Waiting,Semaphore",
|
"Waiting,Semaphore"
|
||||||
#ifndef CONFIG_DISABLE_SIGNALS
|
#ifndef CONFIG_DISABLE_SIGNALS
|
||||||
"Waiting,Signal",
|
, "Waiting,Signal"
|
||||||
#endif
|
#endif
|
||||||
#ifndef CONFIG_DISABLE_MQUEUE
|
#ifndef CONFIG_DISABLE_MQUEUE
|
||||||
"Waiting,MQ empty",
|
, "Waiting,MQ empty"
|
||||||
"Waiting,MQ full"
|
, "Waiting,MQ full"
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_SIG_SIGSTOP_ACTION
|
||||||
|
, "Stopped"
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -245,6 +245,10 @@ enum tstate_e
|
|||||||
#ifdef CONFIG_PAGING
|
#ifdef CONFIG_PAGING
|
||||||
TSTATE_WAIT_PAGEFILL, /* BLOCKED - Waiting for page fill */
|
TSTATE_WAIT_PAGEFILL, /* BLOCKED - Waiting for page fill */
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_SIG_SIGSTOP_ACTION
|
||||||
|
TSTATE_TASK_STOPPED, /* BLOCKED - Waiting for SIGCONT */
|
||||||
|
#endif
|
||||||
|
|
||||||
NUM_TASK_STATES /* Must be last */
|
NUM_TASK_STATES /* Must be last */
|
||||||
};
|
};
|
||||||
typedef enum tstate_e tstate_t;
|
typedef enum tstate_e tstate_t;
|
||||||
|
|||||||
+47
-18
@@ -43,6 +43,7 @@
|
|||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -69,25 +70,27 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(CONFIG_BUILD_FLAT) || defined(__KERNEL__)
|
#if defined(CONFIG_BUILD_FLAT) || defined(__KERNEL__)
|
||||||
# define _SIG_PROCMASK(h,s,o) nxsig_procmask(h,s,o)
|
# define _SIG_PROCMASK(h,s,o) nxsig_procmask(h,s,o)
|
||||||
# define _SIG_QUEUE(p,s,v) nxsig_queue(p,s,v)
|
# define _SIG_SIGACTION(s,a,o) nxsig_action(s,a,o,false)
|
||||||
# define _SIG_KILL(p,s) nxsig_kill(p,s);
|
# define _SIG_QUEUE(p,s,v) nxsig_queue(p,s,v)
|
||||||
# define _SIG_WAITINFO(s,i) nxsig_timedwait(s,i,NULL)
|
# define _SIG_KILL(p,s) nxsig_kill(p,s);
|
||||||
# define _SIG_NANOSLEEP(r,a) nxsig_nanosleep(r,a)
|
# define _SIG_WAITINFO(s,i) nxsig_timedwait(s,i,NULL)
|
||||||
# define _SIG_SLEEP(s) nxsig_sleep(s)
|
# define _SIG_NANOSLEEP(r,a) nxsig_nanosleep(r,a)
|
||||||
# define _SIG_USLEEP(u) nxsig_usleep(u)
|
# define _SIG_SLEEP(s) nxsig_sleep(s)
|
||||||
# define _SIG_ERRNO(r) (-(r))
|
# define _SIG_USLEEP(u) nxsig_usleep(u)
|
||||||
# define _SIG_ERRVAL(r) (r)
|
# define _SIG_ERRNO(r) (-(r))
|
||||||
|
# define _SIG_ERRVAL(r) (r)
|
||||||
#else
|
#else
|
||||||
# define _SIG_PROCMASK(h,s,o) sigprocmask(h,s,o)
|
# define _SIG_PROCMASK(h,s,o) sigprocmask(h,s,o)
|
||||||
# define _SIG_QUEUE(p,s,v) sigqueue(p,s,v)
|
# define _SIG_SIGACTION(s,a,o) sigaction(s,a,o)
|
||||||
# define _SIG_KILL(p,s) kill(p,s);
|
# define _SIG_QUEUE(p,s,v) sigqueue(p,s,v)
|
||||||
# define _SIG_WAITINFO(s,i) sigwaitinfo(s,i)
|
# define _SIG_KILL(p,s) kill(p,s);
|
||||||
# define _SIG_NANOSLEEP(r,a) nanosleep(r,a)
|
# define _SIG_WAITINFO(s,i) sigwaitinfo(s,i)
|
||||||
# define _SIG_SLEEP(s) sleep(s)
|
# define _SIG_NANOSLEEP(r,a) nanosleep(r,a)
|
||||||
# define _SIG_USLEEP(u) usleep(u)
|
# define _SIG_SLEEP(s) sleep(s)
|
||||||
# define _SIG_ERRNO(r) errno
|
# define _SIG_USLEEP(u) usleep(u)
|
||||||
# define _SIG_ERRVAL(r) (-errno)
|
# define _SIG_ERRNO(r) errno
|
||||||
|
# define _SIG_ERRVAL(r) (-errno)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -138,6 +141,32 @@ struct timespec; /* Forward reference */
|
|||||||
|
|
||||||
int nxsig_procmask(int how, FAR const sigset_t *set, FAR sigset_t *oset);
|
int nxsig_procmask(int how, FAR const sigset_t *set, FAR sigset_t *oset);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: nxsig_action
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* This function allows the calling process to examine and/or specify the
|
||||||
|
* action to be associated with a specific signal. This is a non-standard,
|
||||||
|
* OS internal version of the standard sigaction() function. nxsig_action()
|
||||||
|
* adds an additional parameter, force, that is used to set default signal
|
||||||
|
* actions (which may not normally be settable). nxsig_action() does not
|
||||||
|
* alter the errno variable.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* sig - Signal of interest
|
||||||
|
* act - Location of new handler
|
||||||
|
* oact - Location to store only handler
|
||||||
|
* force - Force setup of the signal handler
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* Zero (OK) is returned on success; a negated errno value is returned
|
||||||
|
* on failure.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int nxsig_action(int signo, FAR const struct sigaction *act,
|
||||||
|
FAR struct sigaction *oact, bool force);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: nxsig_queue
|
* Name: nxsig_queue
|
||||||
*
|
*
|
||||||
|
|||||||
+9
-11
@@ -169,17 +169,15 @@
|
|||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_SIG_DEFAULT
|
#ifdef CONFIG_SIG_SIGSTOP_ACTION
|
||||||
# ifndef CONFIG_SIG_INT
|
# define SIGSTOP CONFIG_SIG_STOP
|
||||||
# define SIGINT 6 /* Sent when ctrl-c event */
|
# define SIGSTP CONFIG_SIG_STP
|
||||||
# else
|
# define SIGCONT CONFIG_SIG_CONT
|
||||||
# define SIGINT CONFIG_SIG_INT
|
#endif
|
||||||
# endif
|
|
||||||
# ifndef CONFIG_SIG_KILL
|
#ifdef CONFIG_SIG_SIGKILL_ACTION
|
||||||
# define SIGKILL 9 /* Sent from shell as 'kill -9 <task>' */
|
# define SIGKILL CONFIG_SIG_KILL
|
||||||
# else
|
# define SIGINT CONFIG_SIG_INT
|
||||||
# define SIGKILL CONFIG_SIG_KILL
|
|
||||||
# endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* The following are non-standard signal definitions */
|
/* The following are non-standard signal definitions */
|
||||||
|
|||||||
+62
-13
@@ -1201,30 +1201,52 @@ config SIG_SIGUSR1_ACTION
|
|||||||
bool "SIGUSR1"
|
bool "SIGUSR1"
|
||||||
default n
|
default n
|
||||||
---help---
|
---help---
|
||||||
Enable the default action for SIGUSR1 (terminate the process)
|
Enable the default action for SIGUSR1 (terminate the task)
|
||||||
Make sure that your applications are expecting this POSIX behavior.
|
Make sure that your applications are expecting this POSIX behavior.
|
||||||
|
Backward compatible behavior would require that the application use
|
||||||
|
sigaction() to ignore SIGUSR1.
|
||||||
|
|
||||||
config SIG_SIGUSR2_ACTION
|
config SIG_SIGUSR2_ACTION
|
||||||
bool "SIGUSR2"
|
bool "SIGUSR2"
|
||||||
default n
|
default n
|
||||||
---help---
|
---help---
|
||||||
Enable the default action for SIGUSR2 (terminate the process)
|
Enable the default action for SIGUSR2 (terminate the task)
|
||||||
Make sure that your applications are expecting this POSIX behavior.
|
Make sure that your applications are expecting this POSIX behavior.
|
||||||
|
Backward compatible behavior would require that the application use
|
||||||
|
sigaction() to ignore SIGUSR2.
|
||||||
|
|
||||||
config SIG_SIGALRM_ACTION
|
config SIG_SIGALRM_ACTION
|
||||||
bool "SIGALRM"
|
bool "SIGALRM"
|
||||||
default n
|
default n
|
||||||
---help---
|
---help---
|
||||||
Enable the default action for SIGALRM (terminate the process)
|
Enable the default action for SIGALRM (terminate the task)
|
||||||
Make sure that your applications are expecting this POSIX behavior.
|
Make sure that your applications are expecting this POSIX behavior.
|
||||||
|
Backward compatible behavior would require that the application use
|
||||||
|
sigaction() to ignore SIGALRM.
|
||||||
|
|
||||||
config SIG_SIGPOLL_ACTION
|
config SIG_SIGPOLL_ACTION
|
||||||
bool "SIGPOLL"
|
bool "SIGPOLL"
|
||||||
default n
|
default n
|
||||||
depends on FS_AIO
|
depends on FS_AIO
|
||||||
---help---
|
---help---
|
||||||
Enable the default action for SIGPOLL (terminate the process)
|
Enable the default action for SIGPOLL (terminate the task)
|
||||||
Make sure that your applications are expecting this POSIX behavior.
|
Make sure that your applications are expecting this POSIX behavior.
|
||||||
|
Backward compatible behavior would require that the application use
|
||||||
|
sigaction() to ignore SIGPOLL.
|
||||||
|
|
||||||
|
config SIG_SIGSTOP_ACTION
|
||||||
|
bool "SIGSTOP SIGSTP, and SIGCONT"
|
||||||
|
default y
|
||||||
|
---help---
|
||||||
|
Enable the default action for SIGSTOP and SIGSTP (suspend the
|
||||||
|
task) and SIGCONT (resume the task).
|
||||||
|
|
||||||
|
config SIG_SIGKILL_ACTION
|
||||||
|
bool "SIGINT and SIGKILL"
|
||||||
|
default y
|
||||||
|
---help---
|
||||||
|
Enable the default action for SIGINT and SIGKILL (terminate the
|
||||||
|
task).
|
||||||
|
|
||||||
endif # SIG_DEFAULT
|
endif # SIG_DEFAULT
|
||||||
|
|
||||||
@@ -1269,22 +1291,49 @@ config SIG_POLL
|
|||||||
The SIGPOLL signal is sent to a process when an asynchronous I/O
|
The SIGPOLL signal is sent to a process when an asynchronous I/O
|
||||||
event occurs (meaning it has been polled). Default: 5
|
event occurs (meaning it has been polled). Default: 5
|
||||||
|
|
||||||
config SIG_INT
|
if SIG_DEFAULT
|
||||||
int "SIGINT"
|
|
||||||
|
config SIG_STOP
|
||||||
|
int "SIGSTOP"
|
||||||
default 6
|
default 6
|
||||||
depends on SIG_DEFAULT
|
depends on SIG_SIGSTOP_ACTION
|
||||||
---help---
|
---help---
|
||||||
The SIGINT signal is sent to cause a task termination event (only
|
Suspend/pause a task. SIGSTOP may not be caught or ignored.
|
||||||
if CONFIG_SIG_DEFAULT=y). SIGINT may be ignored or caught by the
|
|
||||||
receiving task.
|
config SIG_STP
|
||||||
|
int "SIGSTP"
|
||||||
|
default 7
|
||||||
|
depends on SIG_SIGSTOP_ACTION
|
||||||
|
---help---
|
||||||
|
Suspend/pause a task. Unlike SIGSTOP, this signal can be caught or
|
||||||
|
ignored.
|
||||||
|
|
||||||
|
config SIG_CONT
|
||||||
|
int "SIGCONT"
|
||||||
|
default 8
|
||||||
|
depends on SIG_SIGSTOP_ACTION
|
||||||
|
---help---
|
||||||
|
Resume a suspended/paused task. SIGSTOP only has an action when
|
||||||
|
send to a stopped task. SIGCONT is ignored by other task. SIGCONT
|
||||||
|
may not be caught or ignored by a stopped task.
|
||||||
|
|
||||||
config SIG_KILL
|
config SIG_KILL
|
||||||
int "SIGKILL"
|
int "SIGKILL"
|
||||||
default 9
|
default 9
|
||||||
depends on SIG_DEFAULT
|
depends on SIG_SIGKILL_ACTION
|
||||||
---help---
|
---help---
|
||||||
The SIGKILL signal is sent to cause a task termination event (only
|
The SIGKILL signal is sent to cause a task termination event.
|
||||||
if CONFIG_SIG_DEFAULT=y). SIGKILL may not be caught or ignored.
|
SIGKILL may not be caught or ignored.
|
||||||
|
|
||||||
|
config SIG_INT
|
||||||
|
int "SIGINT"
|
||||||
|
default 10
|
||||||
|
depends on SIG_SIGKILL_ACTION
|
||||||
|
---help---
|
||||||
|
The SIGINT signal is sent to cause a task termination event.
|
||||||
|
SIGINT may be ignored or caught by the receiving task.
|
||||||
|
|
||||||
|
endif # SIG_DEFAULT
|
||||||
|
|
||||||
comment "Non-standard Signal Numbers"
|
comment "Non-standard Signal Numbers"
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
############################################################################
|
############################################################################
|
||||||
# sched/group/Make.defs
|
# sched/group/Make.defs
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014 Gregory Nutt. All rights reserved.
|
# Copyright (C) 2014, 2018 Gregory Nutt. All rights reserved.
|
||||||
# Author: Gregory Nutt <gnutt@nuttx.org>
|
# Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without
|
# Redistribution and use in source and binary forms, with or without
|
||||||
@@ -52,6 +52,10 @@ ifeq ($(CONFIG_ARCH_ADDRENV),y)
|
|||||||
CSRCS += group_addrenv.c
|
CSRCS += group_addrenv.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_SIG_SIGSTOP_ACTION),y)
|
||||||
|
CSRCS += group_suspendchildren.c group_continue.c
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_BINFMT_LOADABLE),y)
|
ifeq ($(CONFIG_BINFMT_LOADABLE),y)
|
||||||
CSRCS += group_exitinfo.c
|
CSRCS += group_exitinfo.c
|
||||||
endif
|
endif
|
||||||
|
|||||||
+5
-1
@@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* sched/group/group.h
|
* sched/group/group.h
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007-2013, 2015 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2007-2013, 2015, 2018 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -116,6 +116,10 @@ FAR struct task_group_s *group_findbypid(pid_t pid);
|
|||||||
int group_foreachchild(FAR struct task_group_s *group,
|
int group_foreachchild(FAR struct task_group_s *group,
|
||||||
foreachchild_t handler, FAR void *arg);
|
foreachchild_t handler, FAR void *arg);
|
||||||
int group_killchildren(FAR struct task_tcb_s *tcb);
|
int group_killchildren(FAR struct task_tcb_s *tcb);
|
||||||
|
#ifdef CONFIG_SIG_SIGSTOP_ACTION
|
||||||
|
int group_suspendchildren(FAR struct task_tcb_s *tcb);
|
||||||
|
int group_continue(FAR struct task_tcb_s *tcb);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_ARCH_ADDRENV
|
#ifdef CONFIG_ARCH_ADDRENV
|
||||||
|
|||||||
@@ -0,0 +1,128 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* sched/group/group_continue.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
|
||||||
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||||
|
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||||
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <sched.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#include <nuttx/sched.h>
|
||||||
|
|
||||||
|
#include "sched/sched.h"
|
||||||
|
#include "group/group.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_GROUP_MEMBERS
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: group_continue_handler
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Callback from group_foreachchild that handles one member of the group.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* pid - The ID of the group member that may be resumed.
|
||||||
|
* arg - Unused
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* 0 (OK) on success; a negated errno value on failure.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int group_continue_handler(pid_t pid, FAR void *arg)
|
||||||
|
{
|
||||||
|
FAR struct tcb_s *rtcb;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Resume all threads */
|
||||||
|
|
||||||
|
rtcb = sched_gettcb(pid);
|
||||||
|
if (rtc != NULL)
|
||||||
|
{
|
||||||
|
ret = sched_resume(rtcb);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
serr("ERROR: Failed to resume %d: %d\n", ret, pid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Always return zero. We need to visit each member of the group*/
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: group_continue
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Resume all members of the task group. This is SIGCONT default signal
|
||||||
|
* action logic.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* tcb - TCB of the task to be retained.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int group_continue(FAR struct task_tcb_s *tcb)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Lock the scheduler so that there this thread will not lose priority
|
||||||
|
* until all of its children are suspended.
|
||||||
|
*/
|
||||||
|
|
||||||
|
sched_lock();
|
||||||
|
ret = group_foreachchild(tcb->cmn.group, group_continue_handler, NULL);
|
||||||
|
sched_unlock();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HAVE_GROUP_MEMBERS */
|
||||||
@@ -0,0 +1,135 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* sched/group/group_suspendchildren.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
|
||||||
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||||
|
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||||
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <sched.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#include <nuttx/sched.h>
|
||||||
|
|
||||||
|
#include "sched/sched.h"
|
||||||
|
#include "group/group.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_GROUP_MEMBERS
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: group_suspendchildren_handler
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Callback from group_foreachchild that handles one member of the group.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* pid - The ID of the group member that may be suspended.
|
||||||
|
* arg - The PID of the thread to be retained.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* 0 (OK) on success; a negated errno value on failure.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int group_suspendchildren_handler(pid_t pid, FAR void *arg)
|
||||||
|
{
|
||||||
|
FAR struct tcb_s *rtcb;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Suspend all threads except for the one specified by the argument */
|
||||||
|
|
||||||
|
if (pid != (pid_t)((uintptr_t)arg))
|
||||||
|
{
|
||||||
|
/* Suspend this thread if it is still alive. */
|
||||||
|
|
||||||
|
rtcb = sched_gettcb(pid);
|
||||||
|
if (rtcb != NULL)
|
||||||
|
{
|
||||||
|
ret = sched_suspend(rtcb);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
serr("ERROR: Failed to suspend %d: %d\n", ret, pid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Always return zero. We need to visit each member of the group*/
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: group_suspendchildren
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Suspend all children of a task except for the specified task. This is
|
||||||
|
* SIGSTP/SIGSTOP default signal action logic. When the main task is
|
||||||
|
* suspended, all of its child pthreads must also be suspended.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* tcb - TCB of the task to be retained.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int group_suspendchildren(FAR struct task_tcb_s *tcb)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Lock the scheduler so that there this thread will not lose priority
|
||||||
|
* until all of its children are suspended.
|
||||||
|
*/
|
||||||
|
|
||||||
|
sched_lock();
|
||||||
|
ret = group_foreachchild(tcb->cmn.group, group_suspendchildren_handler,
|
||||||
|
(FAR void *)((uintptr_t)tcb->cmn.pid));
|
||||||
|
sched_unlock();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HAVE_GROUP_MEMBERS */
|
||||||
@@ -182,6 +182,12 @@ volatile dq_queue_t g_waitingformqnotfull;
|
|||||||
volatile dq_queue_t g_waitingforfill;
|
volatile dq_queue_t g_waitingforfill;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_SIG_SIGSTOP_ACTION
|
||||||
|
/* This is the list of all tasks that have been stopped via SIGSTOP or SIGSTP */
|
||||||
|
|
||||||
|
volatile dq_queue_t g_stoppedtasks;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* This the list of all tasks that have been initialized, but not yet
|
/* This the list of all tasks that have been initialized, but not yet
|
||||||
* activated. NOTE: This is the only list that is not prioritized.
|
* activated. NOTE: This is the only list that is not prioritized.
|
||||||
*/
|
*/
|
||||||
@@ -300,6 +306,13 @@ const struct tasklist_s g_tasklisttable[NUM_TASK_STATES] =
|
|||||||
TLIST_ATTR_PRIORITIZED
|
TLIST_ATTR_PRIORITIZED
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_SIG_SIGSTOP_ACTION
|
||||||
|
,
|
||||||
|
{ /* TSTATE_TASK_STOPPED */
|
||||||
|
&g_stoppedtasks,
|
||||||
|
0 /* See tcb->prev_state */
|
||||||
|
},
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/* This is the current initialization state. The level of initialization
|
/* This is the current initialization state. The level of initialization
|
||||||
@@ -397,6 +410,9 @@ void os_start(void)
|
|||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_PAGING
|
#ifdef CONFIG_PAGING
|
||||||
dq_init(&g_waitingforfill);
|
dq_init(&g_waitingforfill);
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_SIG_SIGSTOP_ACTION
|
||||||
|
dq_init(&g_stoppedtasks);
|
||||||
#endif
|
#endif
|
||||||
dq_init(&g_inactivetasks);
|
dq_init(&g_inactivetasks);
|
||||||
#if (defined(CONFIG_BUILD_PROTECTED) || defined(CONFIG_BUILD_KERNEL)) && \
|
#if (defined(CONFIG_BUILD_PROTECTED) || defined(CONFIG_BUILD_KERNEL)) && \
|
||||||
|
|||||||
@@ -158,4 +158,5 @@ void irq_dispatch(int irq, FAR void *context)
|
|||||||
/* Then dispatch to the interrupt handler */
|
/* Then dispatch to the interrupt handler */
|
||||||
|
|
||||||
CALL_VECTOR(ndx, vector, irq, context, arg);
|
CALL_VECTOR(ndx, vector, irq, context, arg);
|
||||||
|
UNUSED(ndx);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,6 +54,10 @@ CSRCS += sched_cpuselect.c sched_cpupause.c
|
|||||||
CSRCS += sched_getaffinity.c sched_setaffinity.c
|
CSRCS += sched_getaffinity.c sched_setaffinity.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_SIG_SIGSTOP_ACTION),y)
|
||||||
|
CSRCS += sched_suspend.c sched_continue.c
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_SCHED_WAITPID),y)
|
ifeq ($(CONFIG_SCHED_WAITPID),y)
|
||||||
CSRCS += sched_waitpid.c
|
CSRCS += sched_waitpid.c
|
||||||
ifeq ($(CONFIG_SCHED_HAVE_PARENT),y)
|
ifeq ($(CONFIG_SCHED_HAVE_PARENT),y)
|
||||||
|
|||||||
@@ -440,6 +440,11 @@ uint32_t sched_sporadic_process(FAR struct tcb_s *tcb, uint32_t ticks,
|
|||||||
void sched_sporadic_lowpriority(FAR struct tcb_s *tcb);
|
void sched_sporadic_lowpriority(FAR struct tcb_s *tcb);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_SIG_SIGSTOP_ACTION
|
||||||
|
void sched_suspend(FAR struct tcb_s *tcb);
|
||||||
|
void sched_continue(FAR struct tcb_s *tcb);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
#if defined(CONFIG_ARCH_GLOBAL_IRQDISABLE) || defined(CONFIG_ARCH_HAVE_FETCHADD)
|
#if defined(CONFIG_ARCH_GLOBAL_IRQDISABLE) || defined(CONFIG_ARCH_HAVE_FETCHADD)
|
||||||
FAR struct tcb_s *this_task(void);
|
FAR struct tcb_s *this_task(void);
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* sched/sched/sched_continue.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
|
||||||
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||||
|
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||||
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sched.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <nuttx/irq.h>
|
||||||
|
#include <nuttx/sched.h>
|
||||||
|
#include <nuttx/arch.h>
|
||||||
|
|
||||||
|
#include "sched/sched.h"
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: sched_continue
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Resume the specified thread. This is normally calling indirectly
|
||||||
|
* via group_continue();
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void sched_continue(FAR struct tcb_s *tcb)
|
||||||
|
{
|
||||||
|
irqstate_t flags;
|
||||||
|
|
||||||
|
DEBUGASSERT(tcb != NULL && tcb->task_state == TSTATE_TASK_STOPPED);
|
||||||
|
|
||||||
|
flags = enter_critical_section();
|
||||||
|
|
||||||
|
/* Simply restart the thread. If is was blocked before, it will awaken
|
||||||
|
* with pterrno = EINTR and will appears as if it were awakened by a
|
||||||
|
* signal. If pre-emption is not disabled this action could block this
|
||||||
|
* task here!
|
||||||
|
*/
|
||||||
|
|
||||||
|
up_unblock_task(tcb);
|
||||||
|
leave_critical_section(flags);
|
||||||
|
}
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* sched/sched/sched_suspend.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
|
||||||
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||||
|
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||||
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sched.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <nuttx/irq.h>
|
||||||
|
#include <nuttx/sched.h>
|
||||||
|
#include <nuttx/arch.h>
|
||||||
|
|
||||||
|
#include "sched/sched.h"
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: sched_suspend
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Suspend/pause the specified thread. This is normally calling indirectly
|
||||||
|
* via group_suspendchildren();
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void sched_suspend(FAR struct tcb_s *tcb)
|
||||||
|
{
|
||||||
|
irqstate_t flags;
|
||||||
|
|
||||||
|
DEBUGASSERT(tcb != NULL);
|
||||||
|
|
||||||
|
flags = enter_critical_section();
|
||||||
|
|
||||||
|
/* Check the current state of the task */
|
||||||
|
|
||||||
|
if (tcb->task_state >= FIRST_BLOCKED_STATE &&
|
||||||
|
tcb->task_state <= LAST_BLOCKED_STATE)
|
||||||
|
{
|
||||||
|
/* Remove the TCB from the the blocked task list. */
|
||||||
|
|
||||||
|
sched_removeblocked(tcb);
|
||||||
|
|
||||||
|
/* Set the errno value to EINTR. The task will be restarted in the
|
||||||
|
* running or runnable state and will appear to have awakened from
|
||||||
|
* the block state by a signal.
|
||||||
|
*/
|
||||||
|
|
||||||
|
tcb->pterrno = EINTR;
|
||||||
|
|
||||||
|
/* Move the TCB to the g_stoppedtasks list. */
|
||||||
|
|
||||||
|
sched_addblocked(tcb, TSTATE_TASK_STOPPED);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The task was running or runnable before being stopped. Simply
|
||||||
|
* block it in the stopped state. If tcb refers to this task, then
|
||||||
|
* this action will block this task.
|
||||||
|
*/
|
||||||
|
|
||||||
|
up_block_task(tcb, TSTATE_TASK_STOPPED);
|
||||||
|
}
|
||||||
|
|
||||||
|
leave_critical_section(flags);
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
############################################################################
|
############################################################################
|
||||||
# sched/signal/Make.defs
|
# sched/signal/Make.defs
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014 Gregory Nutt. All rights reserved.
|
# Copyright (C) 2014, 2018 Gregory Nutt. All rights reserved.
|
||||||
# Author: Gregory Nutt <gnutt@nuttx.org>
|
# Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
|||||||
+44
-17
@@ -41,6 +41,7 @@
|
|||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <queue.h>
|
#include <queue.h>
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
@@ -94,7 +95,7 @@ static FAR sigactq_t *nxsig_alloc_action(void)
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: sigaction
|
* Name: nxsig_action and sigaction
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* This function allows the calling process to examine and/or specify the
|
* This function allows the calling process to examine and/or specify the
|
||||||
@@ -123,16 +124,28 @@ static FAR sigactq_t *nxsig_alloc_action(void)
|
|||||||
* original signal mask is restored.
|
* original signal mask is restored.
|
||||||
*
|
*
|
||||||
* Once an action is installed for a specific signal, it remains installed
|
* Once an action is installed for a specific signal, it remains installed
|
||||||
* until another action is explicitly requested by another call to sigaction().
|
* until another action is explicitly requested by another call to
|
||||||
|
* sigaction().
|
||||||
|
*
|
||||||
|
* nxsig_action() is an internal version of sigaction that adds an
|
||||||
|
* additional parameter, force, that is used to set default signal actions
|
||||||
|
* (which may not normally be settable). nxsig_action() does not alter the
|
||||||
|
* errno variable.
|
||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* sig - Signal of interest
|
* sig - Signal of interest
|
||||||
* act - Location of new handler
|
* act - Location of new handler
|
||||||
* oact - Location to store only handler
|
* oact - Location to store only handler
|
||||||
|
* force - Force setup of the signal handler, even if it cannot normally
|
||||||
|
* be caught or ignored (nxsig_action only)
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* 0 (OK), or -1 (ERROR) if the signal number is invalid.
|
* nxsig_action:
|
||||||
* (errno is not set)
|
* Zero (OK) is returned on success; a negated errno value is returned
|
||||||
|
* on failure
|
||||||
|
* sigaction:
|
||||||
|
* Zero (OK) is returned on success; -1 (ERROR) is returned on any
|
||||||
|
* failure if the signal number is invalid with the errno set appropriately
|
||||||
*
|
*
|
||||||
* Assumptions:
|
* Assumptions:
|
||||||
*
|
*
|
||||||
@@ -145,8 +158,8 @@ static FAR sigactq_t *nxsig_alloc_action(void)
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int sigaction(int signo, FAR const struct sigaction *act,
|
int nxsig_action(int signo, FAR const struct sigaction *act,
|
||||||
FAR struct sigaction *oact)
|
FAR struct sigaction *oact, bool force)
|
||||||
{
|
{
|
||||||
FAR struct tcb_s *rtcb = this_task();
|
FAR struct tcb_s *rtcb = this_task();
|
||||||
FAR struct task_group_s *group;
|
FAR struct task_group_s *group;
|
||||||
@@ -164,8 +177,7 @@ int sigaction(int signo, FAR const struct sigaction *act,
|
|||||||
|
|
||||||
if (!GOOD_SIGNO(signo))
|
if (!GOOD_SIGNO(signo))
|
||||||
{
|
{
|
||||||
set_errno(EINVAL);
|
return -EINVAL;
|
||||||
return ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SIG_DEFAULT
|
#ifdef CONFIG_SIG_DEFAULT
|
||||||
@@ -173,11 +185,10 @@ int sigaction(int signo, FAR const struct sigaction *act,
|
|||||||
* caught or ignored.
|
* caught or ignored.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (act != NULL &&
|
if (act != NULL && !force && act->sa_handler != SIG_DFL &&
|
||||||
(act->sa_handler != SIG_DFL && !nxsig_iscatchable(signo)))
|
!nxsig_iscatchable(signo))
|
||||||
{
|
{
|
||||||
set_errno(EINVAL);
|
return -EINVAL;
|
||||||
return ERROR;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -316,8 +327,7 @@ int sigaction(int signo, FAR const struct sigaction *act,
|
|||||||
|
|
||||||
if (!sigact)
|
if (!sigact)
|
||||||
{
|
{
|
||||||
set_errno(ENOMEM);
|
return -ENOMEM;
|
||||||
return ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Put the signal number in the queue entry */
|
/* Put the signal number in the queue entry */
|
||||||
@@ -339,6 +349,23 @@ int sigaction(int signo, FAR const struct sigaction *act,
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sigaction(int signo, FAR const struct sigaction *act,
|
||||||
|
FAR struct sigaction *oact)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* nxsig_action() does all of the work */
|
||||||
|
|
||||||
|
ret = nxsig_action(signo, act, oact, false);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
set_errno(-ret);
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: nxsig_release_action
|
* Name: nxsig_release_action
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -48,6 +48,7 @@
|
|||||||
|
|
||||||
#include <nuttx/sched.h>
|
#include <nuttx/sched.h>
|
||||||
#include <nuttx/irq.h>
|
#include <nuttx/irq.h>
|
||||||
|
#include <nuttx/signal.h>
|
||||||
|
|
||||||
#include "group/group.h"
|
#include "group/group.h"
|
||||||
#include "sched/sched.h"
|
#include "sched/sched.h"
|
||||||
@@ -80,7 +81,9 @@ struct nxsig_defaction_s
|
|||||||
|
|
||||||
/* Default actions */
|
/* Default actions */
|
||||||
|
|
||||||
|
static void nxsig_null_action(int signo);
|
||||||
static void nxsig_abnormal_termination(int signo);
|
static void nxsig_abnormal_termination(int signo);
|
||||||
|
static void nxsig_stop_task(int signo);
|
||||||
|
|
||||||
/* Helpers */
|
/* Helpers */
|
||||||
|
|
||||||
@@ -116,8 +119,15 @@ static const struct nxsig_defaction_s g_defactions[] =
|
|||||||
#ifdef CONFIG_SIG_SIGPOLL_ACTION
|
#ifdef CONFIG_SIG_SIGPOLL_ACTION
|
||||||
{ SIGPOLL, 0, nxsig_abnormal_termination },
|
{ SIGPOLL, 0, nxsig_abnormal_termination },
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_SIG_SIGSTOP_ACTION
|
||||||
|
{ SIGSTOP, SIG_FLAG_NOCATCH, nxsig_stop_task },
|
||||||
|
{ SIGSTP, 0, nxsig_stop_task },
|
||||||
|
{ SIGCONT, SIG_FLAG_NOCATCH, nxsig_null_action },
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_SIG_SIGKILL_ACTION
|
||||||
{ SIGINT, 0, nxsig_abnormal_termination },
|
{ SIGINT, 0, nxsig_abnormal_termination },
|
||||||
{ SIGKILL, SIG_FLAG_NOCATCH, nxsig_abnormal_termination }
|
{ SIGKILL, SIG_FLAG_NOCATCH, nxsig_abnormal_termination }
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NACTIONS (sizeof(g_defactions) / sizeof(struct nxsig_defaction_s))
|
#define NACTIONS (sizeof(g_defactions) / sizeof(struct nxsig_defaction_s))
|
||||||
@@ -142,6 +152,24 @@ static const struct nxsig_defaction_s g_defactions[] =
|
|||||||
* - Continue the process, if it is stopped; otherwise, ignore the signal.
|
* - Continue the process, if it is stopped; otherwise, ignore the signal.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: nxsig_null_action
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* The do-nothing default signal actin handler.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* Standard signal handler parameters
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void nxsig_null_action(int signo)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: nxsig_abnormal_termination
|
* Name: nxsig_abnormal_termination
|
||||||
*
|
*
|
||||||
@@ -195,6 +223,42 @@ static void nxsig_abnormal_termination(int signo)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: nxsig_stop_task
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* This is the handler for the abnormal termination default action.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* Standard signal handler parameters
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void nxsig_stop_task(int signo)
|
||||||
|
{
|
||||||
|
FAR struct tcb_s *rtcb = (FAR struct tcb_s *)this_task();
|
||||||
|
|
||||||
|
/* Careful: In the multi-threaded task, the signal may be handled on a
|
||||||
|
* child pthread.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_GROUP_MEMBERS
|
||||||
|
/* Suspend of of the children of the task. This will not suspend the
|
||||||
|
* currently running task/pthread (this_task). It will suspend the
|
||||||
|
* main thread of the task group if the this_task is a pthread.
|
||||||
|
*/
|
||||||
|
|
||||||
|
group_suspendchildren((FAR struct task_tcb_s *)rtcb);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Then, finally, suspend this thread */
|
||||||
|
|
||||||
|
sched_suspend(rtcb);
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: nxsig_default_action
|
* Name: nxsig_default_action
|
||||||
*
|
*
|
||||||
@@ -260,13 +324,14 @@ static void nxsig_setup_default_action(FAR struct task_group_s *group,
|
|||||||
|
|
||||||
/* Attach the signal handler.
|
/* Attach the signal handler.
|
||||||
*
|
*
|
||||||
* NOTE: sigaction will call nxsig_default(tcb, action, false)
|
* NOTE: nxsig_action will call nxsig_default(tcb, action, false).
|
||||||
|
* Don't be surprised.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
memset(&sa, 0, sizeof(sa));
|
memset(&sa, 0, sizeof(sa));
|
||||||
sa.sa_handler = info->action;
|
sa.sa_handler = info->action;
|
||||||
sa.sa_flags = SA_SIGINFO;
|
sa.sa_flags = SA_SIGINFO;
|
||||||
(void)sigaction(info->signo, &sa, NULL);
|
(void)nxsig_action(info->signo, &sa, NULL, true);
|
||||||
|
|
||||||
/* Indicate that the default signal handler has been attached */
|
/* Indicate that the default signal handler has been attached */
|
||||||
|
|
||||||
|
|||||||
@@ -402,6 +402,22 @@ int nxsig_tcbdispatch(FAR struct tcb_s *stcb, siginfo_t *info)
|
|||||||
nxmq_wait_irq(stcb, EINTR);
|
nxmq_wait_irq(stcb, EINTR);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_SIG_SIGSTOP_ACTION
|
||||||
|
/* If the task was stopped by SIGSTOP or SIGSTP, then unblock the task
|
||||||
|
* if SIGCONT is received.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (stcb->task_state == TSTATE_TASK_STOPPED &&
|
||||||
|
info->si_signo == SIGCONT)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_GROUP_MEMBERS
|
||||||
|
group_continue(stcb);
|
||||||
|
#else
|
||||||
|
sched_continue(stcb);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
Reference in New Issue
Block a user