From 57623d42ebb04f0a0b9e6eb7c0847a3ece2aa0ff Mon Sep 17 00:00:00 2001 From: patacongo Date: Mon, 17 Sep 2012 18:18:44 +0000 Subject: Resync new repository with old repo r5166 git-svn-id: http://svn.code.sf.net/p/nuttx/code/trunk@5153 42af7a65-404d-4744-a932-0658087f49c3 --- nuttx/sched/Kconfig | 419 +++++++++++ nuttx/sched/Makefile | 216 ++++++ nuttx/sched/atexit.c | 162 +++++ nuttx/sched/clock_abstime2ticks.c | 126 ++++ nuttx/sched/clock_dow.c | 88 +++ nuttx/sched/clock_getres.c | 121 ++++ nuttx/sched/clock_gettime.c | 180 +++++ nuttx/sched/clock_gettimeofday.c | 113 +++ nuttx/sched/clock_initialize.c | 270 +++++++ nuttx/sched/clock_internal.h | 91 +++ nuttx/sched/clock_settime.c | 149 ++++ nuttx/sched/clock_systimer.c | 110 +++ nuttx/sched/clock_ticks2time.c | 94 +++ nuttx/sched/clock_time2ticks.c | 102 +++ nuttx/sched/env_clearenv.c | 83 +++ nuttx/sched/env_dup.c | 132 ++++ nuttx/sched/env_dupenv.c | 112 +++ nuttx/sched/env_findvar.c | 131 ++++ nuttx/sched/env_getenv.c | 135 ++++ nuttx/sched/env_getenvironptr.c | 104 +++ nuttx/sched/env_internal.h | 95 +++ nuttx/sched/env_putenv.c | 123 ++++ nuttx/sched/env_release.c | 125 ++++ nuttx/sched/env_removevar.c | 119 ++++ nuttx/sched/env_setenv.c | 208 ++++++ nuttx/sched/env_share.c | 117 +++ nuttx/sched/env_unsetenv.c | 138 ++++ nuttx/sched/errno_get.c | 84 +++ nuttx/sched/errno_getptr.c | 117 +++ nuttx/sched/errno_set.c | 83 +++ nuttx/sched/exit.c | 108 +++ nuttx/sched/getpid.c | 85 +++ nuttx/sched/irq_attach.c | 127 ++++ nuttx/sched/irq_dispatch.c | 105 +++ nuttx/sched/irq_initialize.c | 91 +++ nuttx/sched/irq_internal.h | 83 +++ nuttx/sched/irq_unexpectedisr.c | 88 +++ nuttx/sched/kmm_addregion.c | 113 +++ nuttx/sched/kmm_initialize.c | 113 +++ nuttx/sched/kmm_kfree.c | 110 +++ nuttx/sched/kmm_kmalloc.c | 110 +++ nuttx/sched/kmm_krealloc.c | 111 +++ nuttx/sched/kmm_kzalloc.c | 110 +++ nuttx/sched/kmm_semaphore.c | 140 ++++ nuttx/sched/mq_close.c | 187 +++++ nuttx/sched/mq_descreate.c | 159 +++++ nuttx/sched/mq_findnamed.c | 105 +++ nuttx/sched/mq_initialize.c | 243 +++++++ nuttx/sched/mq_internal.h | 183 +++++ nuttx/sched/mq_msgfree.c | 134 ++++ nuttx/sched/mq_msgqfree.c | 108 +++ nuttx/sched/mq_notify.c | 211 ++++++ nuttx/sched/mq_open.c | 236 +++++++ nuttx/sched/mq_rcvinternal.c | 312 ++++++++ nuttx/sched/mq_receive.c | 166 +++++ nuttx/sched/mq_send.c | 184 +++++ nuttx/sched/mq_sndinternal.c | 455 ++++++++++++ nuttx/sched/mq_timedreceive.c | 303 ++++++++ nuttx/sched/mq_timedsend.c | 319 +++++++++ nuttx/sched/mq_unlink.c | 146 ++++ nuttx/sched/mq_waitirq.c | 172 +++++ nuttx/sched/on_exit.c | 171 +++++ nuttx/sched/os_bringup.c | 194 +++++ nuttx/sched/os_internal.h | 306 ++++++++ nuttx/sched/os_start.c | 466 ++++++++++++ nuttx/sched/pg_internal.h | 126 ++++ nuttx/sched/pg_miss.c | 179 +++++ nuttx/sched/pg_worker.c | 678 ++++++++++++++++++ nuttx/sched/prctl.c | 167 +++++ nuttx/sched/pthread_barrierdestroy.c | 110 +++ nuttx/sched/pthread_barrierinit.c | 122 ++++ nuttx/sched/pthread_barrierwait.c | 182 +++++ nuttx/sched/pthread_cancel.c | 148 ++++ nuttx/sched/pthread_completejoin.c | 231 ++++++ nuttx/sched/pthread_condbroadcast.c | 145 ++++ nuttx/sched/pthread_conddestroy.c | 88 +++ nuttx/sched/pthread_condinit.c | 93 +++ nuttx/sched/pthread_condsignal.c | 137 ++++ nuttx/sched/pthread_condtimedwait.c | 308 ++++++++ nuttx/sched/pthread_condwait.c | 137 ++++ nuttx/sched/pthread_create.c | 435 ++++++++++++ nuttx/sched/pthread_detach.c | 137 ++++ nuttx/sched/pthread_exit.c | 137 ++++ nuttx/sched/pthread_findjoininfo.c | 101 +++ nuttx/sched/pthread_getschedparam.c | 139 ++++ nuttx/sched/pthread_getspecific.c | 123 ++++ nuttx/sched/pthread_initialize.c | 198 ++++++ nuttx/sched/pthread_internal.h | 133 ++++ nuttx/sched/pthread_join.c | 248 +++++++ nuttx/sched/pthread_keycreate.c | 135 ++++ nuttx/sched/pthread_keydelete.c | 96 +++ nuttx/sched/pthread_kill.c | 95 +++ nuttx/sched/pthread_mutexdestroy.c | 131 ++++ nuttx/sched/pthread_mutexinit.c | 138 ++++ nuttx/sched/pthread_mutexlock.c | 187 +++++ nuttx/sched/pthread_mutextrylock.c | 147 ++++ nuttx/sched/pthread_mutexunlock.c | 164 +++++ nuttx/sched/pthread_once.c | 128 ++++ nuttx/sched/pthread_removejoininfo.c | 137 ++++ nuttx/sched/pthread_setcancelstate.c | 131 ++++ nuttx/sched/pthread_setschedparam.c | 142 ++++ nuttx/sched/pthread_setschedprio.c | 120 ++++ nuttx/sched/pthread_setspecific.c | 137 ++++ nuttx/sched/pthread_sigmask.c | 107 +++ nuttx/sched/pthread_yield.c | 87 +++ nuttx/sched/sched_addblocked.c | 122 ++++ nuttx/sched/sched_addprioritized.c | 175 +++++ nuttx/sched/sched_addreadytorun.c | 149 ++++ nuttx/sched/sched_foreach.c | 84 +++ nuttx/sched/sched_free.c | 114 +++ nuttx/sched/sched_garbage.c | 117 +++ nuttx/sched/sched_getfiles.c | 76 ++ nuttx/sched/sched_getparam.c | 146 ++++ nuttx/sched/sched_getscheduler.c | 131 ++++ nuttx/sched/sched_getsockets.c | 77 ++ nuttx/sched/sched_getstreams.c | 76 ++ nuttx/sched/sched_gettcb.c | 107 +++ nuttx/sched/sched_lock.c | 110 +++ nuttx/sched/sched_lockcount.c | 97 +++ nuttx/sched/sched_mergepending.c | 177 +++++ nuttx/sched/sched_processtimer.c | 190 +++++ nuttx/sched/sched_releasefiles.c | 114 +++ nuttx/sched/sched_releasetcb.c | 181 +++++ nuttx/sched/sched_removeblocked.c | 111 +++ nuttx/sched/sched_removereadytorun.c | 121 ++++ nuttx/sched/sched_reprioritize.c | 129 ++++ nuttx/sched/sched_rrgetinterval.c | 157 +++++ nuttx/sched/sched_self.c | 83 +++ nuttx/sched/sched_setparam.c | 156 ++++ nuttx/sched/sched_setpriority.c | 233 ++++++ nuttx/sched/sched_setscheduler.c | 187 +++++ nuttx/sched/sched_setupidlefiles.c | 148 ++++ nuttx/sched/sched_setuppthreadfiles.c | 108 +++ nuttx/sched/sched_setupstreams.c | 98 +++ nuttx/sched/sched_setuptaskfiles.c | 248 +++++++ nuttx/sched/sched_unlock.c | 130 ++++ nuttx/sched/sched_verifytcb.c | 86 +++ nuttx/sched/sched_waitpid.c | 248 +++++++ nuttx/sched/sched_yield.c | 101 +++ nuttx/sched/sem_close.c | 140 ++++ nuttx/sched/sem_destroy.c | 126 ++++ nuttx/sched/sem_findnamed.c | 100 +++ nuttx/sched/sem_holder.c | 1055 ++++++++++++++++++++++++++++ nuttx/sched/sem_initialize.c | 100 +++ nuttx/sched/sem_internal.h | 131 ++++ nuttx/sched/sem_open.c | 209 ++++++ nuttx/sched/sem_post.c | 182 +++++ nuttx/sched/sem_timedwait.c | 286 ++++++++ nuttx/sched/sem_trywait.c | 142 ++++ nuttx/sched/sem_unlink.c | 140 ++++ nuttx/sched/sem_wait.c | 216 ++++++ nuttx/sched/sem_waitirq.c | 145 ++++ nuttx/sched/sig_action.c | 272 +++++++ nuttx/sched/sig_allocatependingsigaction.c | 137 ++++ nuttx/sched/sig_cleanup.c | 118 ++++ nuttx/sched/sig_deliver.c | 159 +++++ nuttx/sched/sig_findaction.c | 100 +++ nuttx/sched/sig_initialize.c | 271 +++++++ nuttx/sched/sig_internal.h | 190 +++++ nuttx/sched/sig_kill.c | 135 ++++ nuttx/sched/sig_lowest.c | 91 +++ nuttx/sched/sig_mqnotempty.c | 128 ++++ nuttx/sched/sig_pending.c | 130 ++++ nuttx/sched/sig_procmask.c | 180 +++++ nuttx/sched/sig_queue.c | 159 +++++ nuttx/sched/sig_received.c | 404 +++++++++++ nuttx/sched/sig_releasependingsigaction.c | 120 ++++ nuttx/sched/sig_releasependingsignal.c | 131 ++++ nuttx/sched/sig_removependingsignal.c | 115 +++ nuttx/sched/sig_suspend.c | 180 +++++ nuttx/sched/sig_timedwait.c | 334 +++++++++ nuttx/sched/sig_unmaskpendingsignal.c | 138 ++++ nuttx/sched/sig_waitinfo.c | 89 +++ nuttx/sched/sleep.c | 196 ++++++ nuttx/sched/task_activate.c | 117 +++ nuttx/sched/task_create.c | 269 +++++++ nuttx/sched/task_delete.c | 194 +++++ nuttx/sched/task_deletecurrent.c | 140 ++++ nuttx/sched/task_exithook.c | 290 ++++++++ nuttx/sched/task_init.c | 154 ++++ nuttx/sched/task_restart.c | 184 +++++ nuttx/sched/task_setup.c | 347 +++++++++ nuttx/sched/task_start.c | 114 +++ nuttx/sched/timer_create.c | 237 +++++++ nuttx/sched/timer_delete.c | 106 +++ nuttx/sched/timer_getoverrun.c | 111 +++ nuttx/sched/timer_gettime.c | 123 ++++ nuttx/sched/timer_initialize.c | 168 +++++ nuttx/sched/timer_internal.h | 102 +++ nuttx/sched/timer_release.c | 159 +++++ nuttx/sched/timer_settime.c | 397 +++++++++++ nuttx/sched/usleep.c | 168 +++++ nuttx/sched/wd_cancel.c | 165 +++++ nuttx/sched/wd_create.c | 109 +++ nuttx/sched/wd_delete.c | 127 ++++ nuttx/sched/wd_gettime.c | 118 ++++ nuttx/sched/wd_initialize.c | 135 ++++ nuttx/sched/wd_internal.h | 119 ++++ nuttx/sched/wd_start.c | 375 ++++++++++ nuttx/sched/work_cancel.c | 127 ++++ nuttx/sched/work_internal.h | 114 +++ nuttx/sched/work_queue.c | 138 ++++ nuttx/sched/work_signal.c | 96 +++ nuttx/sched/work_thread.c | 256 +++++++ 204 files changed, 33580 insertions(+) create mode 100644 nuttx/sched/Kconfig create mode 100644 nuttx/sched/Makefile create mode 100644 nuttx/sched/atexit.c create mode 100644 nuttx/sched/clock_abstime2ticks.c create mode 100644 nuttx/sched/clock_dow.c create mode 100644 nuttx/sched/clock_getres.c create mode 100644 nuttx/sched/clock_gettime.c create mode 100644 nuttx/sched/clock_gettimeofday.c create mode 100644 nuttx/sched/clock_initialize.c create mode 100644 nuttx/sched/clock_internal.h create mode 100644 nuttx/sched/clock_settime.c create mode 100644 nuttx/sched/clock_systimer.c create mode 100644 nuttx/sched/clock_ticks2time.c create mode 100644 nuttx/sched/clock_time2ticks.c create mode 100644 nuttx/sched/env_clearenv.c create mode 100644 nuttx/sched/env_dup.c create mode 100644 nuttx/sched/env_dupenv.c create mode 100644 nuttx/sched/env_findvar.c create mode 100644 nuttx/sched/env_getenv.c create mode 100644 nuttx/sched/env_getenvironptr.c create mode 100644 nuttx/sched/env_internal.h create mode 100644 nuttx/sched/env_putenv.c create mode 100644 nuttx/sched/env_release.c create mode 100644 nuttx/sched/env_removevar.c create mode 100644 nuttx/sched/env_setenv.c create mode 100644 nuttx/sched/env_share.c create mode 100644 nuttx/sched/env_unsetenv.c create mode 100644 nuttx/sched/errno_get.c create mode 100644 nuttx/sched/errno_getptr.c create mode 100644 nuttx/sched/errno_set.c create mode 100644 nuttx/sched/exit.c create mode 100644 nuttx/sched/getpid.c create mode 100644 nuttx/sched/irq_attach.c create mode 100644 nuttx/sched/irq_dispatch.c create mode 100644 nuttx/sched/irq_initialize.c create mode 100644 nuttx/sched/irq_internal.h create mode 100644 nuttx/sched/irq_unexpectedisr.c create mode 100644 nuttx/sched/kmm_addregion.c create mode 100644 nuttx/sched/kmm_initialize.c create mode 100644 nuttx/sched/kmm_kfree.c create mode 100644 nuttx/sched/kmm_kmalloc.c create mode 100644 nuttx/sched/kmm_krealloc.c create mode 100644 nuttx/sched/kmm_kzalloc.c create mode 100644 nuttx/sched/kmm_semaphore.c create mode 100644 nuttx/sched/mq_close.c create mode 100644 nuttx/sched/mq_descreate.c create mode 100644 nuttx/sched/mq_findnamed.c create mode 100644 nuttx/sched/mq_initialize.c create mode 100644 nuttx/sched/mq_internal.h create mode 100644 nuttx/sched/mq_msgfree.c create mode 100644 nuttx/sched/mq_msgqfree.c create mode 100644 nuttx/sched/mq_notify.c create mode 100644 nuttx/sched/mq_open.c create mode 100644 nuttx/sched/mq_rcvinternal.c create mode 100644 nuttx/sched/mq_receive.c create mode 100644 nuttx/sched/mq_send.c create mode 100644 nuttx/sched/mq_sndinternal.c create mode 100644 nuttx/sched/mq_timedreceive.c create mode 100644 nuttx/sched/mq_timedsend.c create mode 100644 nuttx/sched/mq_unlink.c create mode 100644 nuttx/sched/mq_waitirq.c create mode 100644 nuttx/sched/on_exit.c create mode 100644 nuttx/sched/os_bringup.c create mode 100644 nuttx/sched/os_internal.h create mode 100644 nuttx/sched/os_start.c create mode 100644 nuttx/sched/pg_internal.h create mode 100644 nuttx/sched/pg_miss.c create mode 100644 nuttx/sched/pg_worker.c create mode 100644 nuttx/sched/prctl.c create mode 100644 nuttx/sched/pthread_barrierdestroy.c create mode 100644 nuttx/sched/pthread_barrierinit.c create mode 100644 nuttx/sched/pthread_barrierwait.c create mode 100644 nuttx/sched/pthread_cancel.c create mode 100644 nuttx/sched/pthread_completejoin.c create mode 100644 nuttx/sched/pthread_condbroadcast.c create mode 100644 nuttx/sched/pthread_conddestroy.c create mode 100644 nuttx/sched/pthread_condinit.c create mode 100644 nuttx/sched/pthread_condsignal.c create mode 100644 nuttx/sched/pthread_condtimedwait.c create mode 100644 nuttx/sched/pthread_condwait.c create mode 100644 nuttx/sched/pthread_create.c create mode 100644 nuttx/sched/pthread_detach.c create mode 100644 nuttx/sched/pthread_exit.c create mode 100644 nuttx/sched/pthread_findjoininfo.c create mode 100644 nuttx/sched/pthread_getschedparam.c create mode 100644 nuttx/sched/pthread_getspecific.c create mode 100644 nuttx/sched/pthread_initialize.c create mode 100644 nuttx/sched/pthread_internal.h create mode 100644 nuttx/sched/pthread_join.c create mode 100644 nuttx/sched/pthread_keycreate.c create mode 100644 nuttx/sched/pthread_keydelete.c create mode 100644 nuttx/sched/pthread_kill.c create mode 100644 nuttx/sched/pthread_mutexdestroy.c create mode 100644 nuttx/sched/pthread_mutexinit.c create mode 100644 nuttx/sched/pthread_mutexlock.c create mode 100644 nuttx/sched/pthread_mutextrylock.c create mode 100644 nuttx/sched/pthread_mutexunlock.c create mode 100644 nuttx/sched/pthread_once.c create mode 100644 nuttx/sched/pthread_removejoininfo.c create mode 100644 nuttx/sched/pthread_setcancelstate.c create mode 100644 nuttx/sched/pthread_setschedparam.c create mode 100644 nuttx/sched/pthread_setschedprio.c create mode 100644 nuttx/sched/pthread_setspecific.c create mode 100644 nuttx/sched/pthread_sigmask.c create mode 100644 nuttx/sched/pthread_yield.c create mode 100644 nuttx/sched/sched_addblocked.c create mode 100644 nuttx/sched/sched_addprioritized.c create mode 100644 nuttx/sched/sched_addreadytorun.c create mode 100644 nuttx/sched/sched_foreach.c create mode 100644 nuttx/sched/sched_free.c create mode 100644 nuttx/sched/sched_garbage.c create mode 100644 nuttx/sched/sched_getfiles.c create mode 100644 nuttx/sched/sched_getparam.c create mode 100644 nuttx/sched/sched_getscheduler.c create mode 100644 nuttx/sched/sched_getsockets.c create mode 100644 nuttx/sched/sched_getstreams.c create mode 100644 nuttx/sched/sched_gettcb.c create mode 100644 nuttx/sched/sched_lock.c create mode 100644 nuttx/sched/sched_lockcount.c create mode 100644 nuttx/sched/sched_mergepending.c create mode 100644 nuttx/sched/sched_processtimer.c create mode 100644 nuttx/sched/sched_releasefiles.c create mode 100644 nuttx/sched/sched_releasetcb.c create mode 100644 nuttx/sched/sched_removeblocked.c create mode 100644 nuttx/sched/sched_removereadytorun.c create mode 100644 nuttx/sched/sched_reprioritize.c create mode 100644 nuttx/sched/sched_rrgetinterval.c create mode 100644 nuttx/sched/sched_self.c create mode 100644 nuttx/sched/sched_setparam.c create mode 100644 nuttx/sched/sched_setpriority.c create mode 100644 nuttx/sched/sched_setscheduler.c create mode 100644 nuttx/sched/sched_setupidlefiles.c create mode 100644 nuttx/sched/sched_setuppthreadfiles.c create mode 100644 nuttx/sched/sched_setupstreams.c create mode 100644 nuttx/sched/sched_setuptaskfiles.c create mode 100644 nuttx/sched/sched_unlock.c create mode 100644 nuttx/sched/sched_verifytcb.c create mode 100644 nuttx/sched/sched_waitpid.c create mode 100644 nuttx/sched/sched_yield.c create mode 100644 nuttx/sched/sem_close.c create mode 100644 nuttx/sched/sem_destroy.c create mode 100644 nuttx/sched/sem_findnamed.c create mode 100644 nuttx/sched/sem_holder.c create mode 100644 nuttx/sched/sem_initialize.c create mode 100644 nuttx/sched/sem_internal.h create mode 100644 nuttx/sched/sem_open.c create mode 100644 nuttx/sched/sem_post.c create mode 100644 nuttx/sched/sem_timedwait.c create mode 100644 nuttx/sched/sem_trywait.c create mode 100644 nuttx/sched/sem_unlink.c create mode 100644 nuttx/sched/sem_wait.c create mode 100644 nuttx/sched/sem_waitirq.c create mode 100644 nuttx/sched/sig_action.c create mode 100644 nuttx/sched/sig_allocatependingsigaction.c create mode 100644 nuttx/sched/sig_cleanup.c create mode 100644 nuttx/sched/sig_deliver.c create mode 100644 nuttx/sched/sig_findaction.c create mode 100644 nuttx/sched/sig_initialize.c create mode 100644 nuttx/sched/sig_internal.h create mode 100644 nuttx/sched/sig_kill.c create mode 100644 nuttx/sched/sig_lowest.c create mode 100644 nuttx/sched/sig_mqnotempty.c create mode 100644 nuttx/sched/sig_pending.c create mode 100644 nuttx/sched/sig_procmask.c create mode 100644 nuttx/sched/sig_queue.c create mode 100644 nuttx/sched/sig_received.c create mode 100644 nuttx/sched/sig_releasependingsigaction.c create mode 100644 nuttx/sched/sig_releasependingsignal.c create mode 100644 nuttx/sched/sig_removependingsignal.c create mode 100644 nuttx/sched/sig_suspend.c create mode 100644 nuttx/sched/sig_timedwait.c create mode 100644 nuttx/sched/sig_unmaskpendingsignal.c create mode 100644 nuttx/sched/sig_waitinfo.c create mode 100644 nuttx/sched/sleep.c create mode 100644 nuttx/sched/task_activate.c create mode 100644 nuttx/sched/task_create.c create mode 100644 nuttx/sched/task_delete.c create mode 100644 nuttx/sched/task_deletecurrent.c create mode 100644 nuttx/sched/task_exithook.c create mode 100644 nuttx/sched/task_init.c create mode 100644 nuttx/sched/task_restart.c create mode 100644 nuttx/sched/task_setup.c create mode 100644 nuttx/sched/task_start.c create mode 100644 nuttx/sched/timer_create.c create mode 100644 nuttx/sched/timer_delete.c create mode 100644 nuttx/sched/timer_getoverrun.c create mode 100644 nuttx/sched/timer_gettime.c create mode 100644 nuttx/sched/timer_initialize.c create mode 100644 nuttx/sched/timer_internal.h create mode 100644 nuttx/sched/timer_release.c create mode 100644 nuttx/sched/timer_settime.c create mode 100644 nuttx/sched/usleep.c create mode 100644 nuttx/sched/wd_cancel.c create mode 100644 nuttx/sched/wd_create.c create mode 100644 nuttx/sched/wd_delete.c create mode 100644 nuttx/sched/wd_gettime.c create mode 100644 nuttx/sched/wd_initialize.c create mode 100644 nuttx/sched/wd_internal.h create mode 100644 nuttx/sched/wd_start.c create mode 100644 nuttx/sched/work_cancel.c create mode 100644 nuttx/sched/work_internal.h create mode 100644 nuttx/sched/work_queue.c create mode 100644 nuttx/sched/work_signal.c create mode 100644 nuttx/sched/work_thread.c (limited to 'nuttx/sched') diff --git a/nuttx/sched/Kconfig b/nuttx/sched/Kconfig new file mode 100644 index 000000000..4f7149595 --- /dev/null +++ b/nuttx/sched/Kconfig @@ -0,0 +1,419 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config MSEC_PER_TICK + int "tick timer" + default 10 + ---help--- + The default system timer is 100Hz or MSEC_PER_TICK=10. This setting + may be defined to inform NuttX that the processor hardware is providing + system timer interrupts at some interrupt interval other than 10 msec. + +config RR_INTERVAL + int "round robin timeslice" + default 0 + ---help--- + The round robin timeslice will be set this number of milliseconds; + Round robin scheduling can be disabled by setting this value to zero. + +config SCHED_INSTRUMENTATION + bool "Monitor system performance" + default n + ---help--- + enables instrumentation in scheduler to monitor system performance. + +config TASK_NAME_SIZE + int "Maximum task name size" + default 32 + ---help--- + Spcifies that maximum size of a task name to save in the TCB. + Useful if scheduler instrumentation is selected. Set to zero to + disable. + +config JULIAN_TIME + bool "Enables Julian time conversions" + default n + ---help--- + Enables Julian time conversions + +config START_YEAR + int "start year" + default 2010 + +config START_MONTH + int "start month" + default 1 + +config START_DAY + int "start day" + default 1 + +config DEV_CONSOLE + bool "Enable /dev/console" + default y + ---help--- + Set if architecture-specific logic provides /dev/console. Enables + stdout, stderr, stdin. + +config DEV_LOWCONSOLE + bool "enable low-level serial console" + default n + ---help--- + Use the simple, low-level, write-only serial console driver (minimul support) + +config MUTEX_TYPES: + bool "Enable mutex types" + default n + ---help--- + Set to enable support for recursive and errorcheck mutexes. Enables + pthread_mutexattr_settype(). + +config PRIORITY_INHERITANCE + bool "Enable priority inheritance " + default n + ---help--- + Set to enable support for priority inheritance on mutexes and semaphores. + +config SEM_PREALLOCHOLDERS + int "Pre-allocated holders" + default 16 + depends on PRIORITY_INHERITANCE + ---help--- + This setting is only used if priority inheritance is enabled. + It defines the maximum number of different threads (minus one) that + can take counts on a semaphore with priority inheritance support. + This may be set to zero if priority inheritance is disabled OR if you + are only using semaphores as mutexes (only one holder) OR if no more + than two threads participate using a counting semaphore. + +config SEM_NNESTPRIO + int "Maximum number of higher priority threads" + default 16 + depends on PRIORITY_INHERITANCE + ---help--- + If priority inheritance is enabled, then this setting is the + maximum number of higher priority threads (minus 1) than can be + waiting for another thread to release a count on a semaphore. + This value may be set to zero if no more than one thread is + expected to wait for a semaphore. + +config FDCLONE_DISABLE + bool "Disable cloning of file descriptors" + default n + ---help--- + Disable cloning of all file descriptors + by task_create() when a new task is started. If set, all + files/drivers will appear to be closed in the new task. + +config FDCLONE_STDIO + bool "Disable clone file descriptors without stdio" + default n + ---help--- + Disable cloning of all but the first three file descriptors (stdin, + stdout, stderr) by task_create() when a new task is started. If set, + all files/drivers will appear to be closed in the new task except + for stdin, stdout, and stderr. + +config SDCLONE_DISABLE + bool "Disable cloning of socket descriptors" + default n + ---help--- + Disable cloning of all socket + desciptors by task_create() when a new task is started. If + set, all sockets will appear to be closed in the new task. + +config SCHED_WORKQUEUE + bool "Enable worker thread" + default n + ---help--- + Create a dedicated "worker" thread to handle delayed processing from interrupt + handlers. This feature is required for some drivers but, if there are no + complaints, can be safely disabled. The worker thread also performs + garbage collection -- completing any delayed memory deallocations from + interrupt handlers. If the worker thread is disabled, then that clean up will + be performed by the IDLE thread instead (which runs at the lowest of priority + and may not be appropriate if memory reclamation is of high priority). + +config SCHED_WORKPRIORITY + int "Worker thread priority" + default 192 + depends on SCHED_WORKQUEUE + ---help--- + The execution priority of the worker thread. Default: 192 + +config SCHED_WORKPERIOD + int "Worker thread period" + default 50000 + depends on SCHED_WORKQUEUE + ---help--- + How often the worker thread checks for work in units of microseconds. + Default: 50*1000 (50 MS). + +config SCHED_WORKSTACKSIZE + int "Worker thread stack size" + default 2048 + depends on SCHED_WORKQUEUE + ---help--- + The stack size allocated for the worker thread. Default: 2K. + +config SIG_SIGWORK + int "Worker thread wakeup signal" + default 4 + depends on SCHED_WORKQUEUE + ---help--- + The signal number that will be used to wake-up the worker thread. + Default: 4 + +config SCHED_LPWORK + bool "Enable a lower priority worker thread" + default n + depends on SCHED_WORKQUEUE + ---help--- + If SCHED_WORKQUEUE is defined, then a single work queue is created by + default. If SCHED_LPWORK is also defined then an additional, lower- + priority work queue will also be created. This lower priority work + queue is better suited for more extended processing (such as file system + clean-up operations) + +config SCHED_LPWORKPRIORITY + int "Lower priority worker thread priority" + default 50 + depends on SCHED_LPWORK + ---help--- + The execution priority of the lopwer priority worker thread. Default: 192 + +config SCHED_LPWORKPERIOD + int "Lower priority worker thread period" + default 50000 + depends on SCHED_LPWORK + ---help--- + How often the lower priority worker thread checks for work in units + of microseconds. Default: 50*1000 (50 MS). + +config SCHED_LPWORKSTACKSIZE + int "Lower priority worker thread stack size" + default 2048 + depends on SCHED_LPWORK + ---help--- + The stack size allocated for the lower priority worker thread. Default: 2K. + +config SCHED_WAITPID + bool "Enable waitpid() API" + default n + ---help--- + Enables the waitpid() API + +config SCHED_ATEXIT + bool "Enable atexit() API" + default n + ---help--- + Enables the atexit() API + +config SCHED_ATEXIT_MAX + int "Max number of atexit() functions" + default 1 + depends on SCHED_ATEXIT + ---help--- + By default if SCHED_ATEXIT is selected, only a single atexit() function + is supported. That number can be increased by defined this setting to + the number that you require. + +config SCHED_ONEXIT + bool "Enable on_exit() API" + default n + ---help--- + Enables the on_exit() API + +config SCHED_ONEXIT_MAX + int "Max number of on_exit() functions" + default 1 + depends on SCHED_ONEXIT + ---help--- + By default if SCHED_ONEXIT is selected, only a single on_exit() function + is supported. That number can be increased by defined this setting to the + number that you require. + +config USER_ENTRYPOINT + string "Application entry point" + default "user_start" + ---help--- + The name of the entry point for user applications. For the example + applications this is of the form 'app_main' where 'app' is the application + name. If not defined, USER_ENTRYPOINT defaults to "user_start." + +config DISABLE_OS_API + bool "Disable NuttX interfaces" + default y + ---help--- + The following can be used to disable categories of + APIs supported by the OS. If the compiler supports + weak functions, then it should not be necessary to + disable functions unless you want to restrict usage + of those APIs. + + There are certain dependency relationships in these + features. + + o mq_notify logic depends on signals to awaken tasks + waiting for queues to become full or empty. + o pthread_condtimedwait() depends on signals to wake + up waiting tasks. + +config DISABLE_CLOCK + bool "Disable clock interfaces" + depends on DISABLE_OS_API + default n + +config DISABLE_POSIX_TIMERS + bool "Disable POSIX timers" + depends on DISABLE_OS_API + default n + +config DISABLE_PTHREAD + bool "Disable pthread support" + depends on DISABLE_OS_API + default n + +config DISABLE_SIGNALS + bool "Disable signal support" + depends on DISABLE_OS_API + default n + +config DISABLE_MQUEUE + bool "Disable POSIX message queue support" + depends on DISABLE_OS_API + default n + +config DISABLE_MOUNTPOINT + bool "Disable support for mount points" + depends on DISABLE_OS_API + default n + +config DISABLE_ENVIRON + bool "Disable environment variable support" + depends on DISABLE_OS_API + default n + +config DISABLE_POLL + bool "Disable driver poll interfaces" + depends on DISABLE_OS_API + default n + +comment "Sizes of configurable things (0 disables)" + +config MAX_TASKS + int "Max tasks" + default 32 + ---help--- + The maximum number of simultaneously active tasks. This value must be + a power of two. + +config MAX_TASK_ARGS + int "Maximum number of task arguments" + default 4 + ---help--- + This controls the maximum number of of parameters that a task may + receive (i.e., maxmum value of 'argc') + +config NPTHREAD_KEYS + int "Number of pthread keys" + default 4 + ---help--- + The number of items of thread- + specific data that can be retained + +config NFILE_DESCRIPTORS + int "Max file descriptors" + default 16 + ---help--- + The maximum number of file + descriptors (one for each open) + +config NFILE_STREAMS + int "Max file streams" + default 16 + ---help--- + The maximum number of streams that can be fopen'ed + +config NAME_MAX + int "name max" + default 32 + ---help--- + The maximum size of a file name. + +config PREALLOC_MQ_MSGS + int "Pre-allocated messages" + default 32 + ---help--- + The number of pre-allocated message structures. The system manages + a pool of preallocated message structures to minimize dynamic allocations + +config MQ_MAXMSGSIZE + int "Maximum message size" + default 32 + ---help--- + Message structures are allocated with a fixed payload size given by this + setting (does not include other message structure overhead. + +config MAX_WDOGPARMS + int "max watchdog parms" + default 4 + ---help--- + Maximum number of parameters that + can be passed to a watchdog handler + +config PREALLOC_WDOGS + int "Pre-allocated watchdogs" + default 32 + ---help--- + The number of pre-allocated watchdog structures. The system manages a + pool of preallocated watchdog structures to minimize dynamic allocations + +config PREALLOC_TIMERS + int "Pre-allocated timers" + default 8 + ---help--- + The number of pre-allocated POSIX timer structures. The system manages a + pool of preallocated timer structures to minimize dynamic allocations. Set to + zero for all dynamic allocations. + +comment "Stack and heap information" + +config CUSTOM_STACK + bool "Enable custom stack" + default n + ---help--- + The up_ implementation will handle all stack operations outside of the + nuttx model. This is necessary for certain architectures that have + have hardware stacks (such as the 8051 family). + +config IDLETHREAD_STACKSIZE + int "Idle thread stack size" + default 1024 + ---help--- + The size of the initial stack used by the IDLE thread. The IDLE thread + is the thread that (1) performs the inital boot of the system up to the + point where user_start() is spawned, and (2) there after is the IDLE + thread that executes only when there is no other thread ready to run. + +config USERMAIN_STACKSIZE + int "Main thread stack size" + default 2048 + ---help--- + The size of the stack to allocate for the main user thread that begins at + the user_start() entry point. + +config PTHREAD_STACK_MIN + int "Minimum pthread stack size" + default 256 + ---help--- + Minimum pthread stack size + +config PTHREAD_STACK_DEFAULT + int "Default pthread stack size" + default 2048 + ---help--- + Default pthread stack size + diff --git a/nuttx/sched/Makefile b/nuttx/sched/Makefile new file mode 100644 index 000000000..1e0a55aea --- /dev/null +++ b/nuttx/sched/Makefile @@ -0,0 +1,216 @@ +############################################################################ +# sched/Makefile +# +# Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# 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. +# +############################################################################ + +-include $(TOPDIR)/Make.defs + +ASRCS = +AOBJS = $(ASRCS:.S=$(OBJEXT)) + +MISC_SRCS = os_start.c os_bringup.c errno_getptr.c errno_get.c errno_set.c \ + sched_garbage.c sched_setupstreams.c sched_getfiles.c sched_getsockets.c \ + sched_getstreams.c sched_setupidlefiles.c sched_setuptaskfiles.c \ + sched_setuppthreadfiles.c sched_releasefiles.c + +TSK_SRCS = prctl.c task_create.c task_init.c task_setup.c task_activate.c \ + task_start.c task_delete.c task_deletecurrent.c task_exithook.c \ + task_restart.c exit.c getpid.c sched_addreadytorun.c \ + sched_removereadytorun.c sched_addprioritized.c sched_mergepending.c \ + sched_addblocked.c sched_removeblocked.c sched_free.c sched_gettcb.c \ + sched_verifytcb.c sched_releasetcb.c + +SCHED_SRCS = sched_setparam.c sched_setpriority.c sched_getparam.c \ + sched_setscheduler.c sched_getscheduler.c \ + sched_yield.c sched_rrgetinterval.c sched_foreach.c \ + sched_lock.c sched_unlock.c sched_lockcount.c sched_self.c + +ifeq ($(CONFIG_SCHED_ATEXIT),y) +SCHED_SRCS += atexit.c +endif + +ifeq ($(CONFIG_SCHED_ONEXIT),y) +SCHED_SRCS += on_exit.c +endif + +ifeq ($(CONFIG_PRIORITY_INHERITANCE),y) +SCHED_SRCS += sched_reprioritize.c +endif + +ifeq ($(CONFIG_SCHED_WAITPID),y) +SCHED_SRCS += sched_waitpid.c +endif + +ENV_SRCS = env_getenvironptr.c env_dup.c env_share.c env_release.c \ + env_findvar.c env_removevar.c \ + env_clearenv.c env_getenv.c env_putenv.c env_setenv.c env_unsetenv.c + +WDOG_SRCS = wd_initialize.c wd_create.c wd_start.c wd_cancel.c wd_delete.c \ + wd_gettime.c + +TIME_SRCS = sched_processtimer.c + +ifneq ($(CONFIG_DISABLE_SIGNALS),y) +TIME_SRCS += sleep.c usleep.c +endif + +CLOCK_SRCS = clock_initialize.c clock_settime.c clock_gettime.c clock_getres.c \ + clock_time2ticks.c clock_abstime2ticks.c clock_ticks2time.c \ + clock_gettimeofday.c clock_systimer.c + +SIGNAL_SRCS = sig_initialize.c \ + sig_action.c sig_procmask.c sig_pending.c sig_suspend.c \ + sig_kill.c sig_queue.c sig_waitinfo.c sig_timedwait.c \ + sig_findaction.c sig_allocatependingsigaction.c \ + sig_releasependingsigaction.c sig_unmaskpendingsignal.c \ + sig_removependingsignal.c sig_releasependingsignal.c sig_lowest.c \ + sig_mqnotempty.c sig_cleanup.c sig_received.c sig_deliver.c + +MQUEUE_SRCS = mq_open.c mq_close.c mq_unlink.c mq_send.c mq_timedsend.c\ + mq_sndinternal.c mq_receive.c mq_timedreceive.c mq_rcvinternal.c \ + mq_initialize.c mq_descreate.c mq_findnamed.c mq_msgfree.c mq_msgqfree.c + +ifneq ($(CONFIG_DISABLE_SIGNALS),y) +MQUEUE_SRCS += mq_waitirq.c +endif + +ifneq ($(CONFIG_DISABLE_SIGNALS),y) +MQUEUE_SRCS += mq_notify.c +endif + +PTHREAD_SRCS = pthread_create.c pthread_exit.c pthread_join.c pthread_detach.c \ + pthread_yield.c pthread_getschedparam.c pthread_setschedparam.c \ + pthread_mutexinit.c pthread_mutexdestroy.c \ + pthread_mutexlock.c pthread_mutextrylock.c pthread_mutexunlock.c \ + pthread_condinit.c pthread_conddestroy.c \ + pthread_condwait.c pthread_condsignal.c pthread_condbroadcast.c \ + pthread_barrierinit.c pthread_barrierdestroy.c pthread_barrierwait.c \ + pthread_cancel.c pthread_setcancelstate.c \ + pthread_keycreate.c pthread_setspecific.c pthread_getspecific.c pthread_keydelete.c \ + pthread_initialize.c pthread_completejoin.c pthread_findjoininfo.c \ + pthread_removejoininfo.c pthread_once.c pthread_setschedprio.c + +ifneq ($(CONFIG_DISABLE_SIGNALS),y) +PTHREAD_SRCS += pthread_condtimedwait.c pthread_kill.c pthread_sigmask.c +endif + +SEM_SRCS = sem_initialize.c sem_destroy.c sem_open.c sem_close.c sem_unlink.c \ + sem_wait.c sem_trywait.c sem_timedwait.c sem_post.c sem_findnamed.c + +ifneq ($(CONFIG_DISABLE_SIGNALS),y) +SEM_SRCS += sem_waitirq.c +endif + +ifeq ($(CONFIG_PRIORITY_INHERITANCE),y) +SEM_SRCS += sem_holder.c +endif + +ifneq ($(CONFIG_DISABLE_POSIX_TIMERS),y) +TIMER_SRCS = timer_initialize.c timer_create.c timer_delete.c timer_getoverrun.c \ + timer_gettime.c timer_settime.c timer_release.c +endif + +ifeq ($(CONFIG_SCHED_WORKQUEUE),y) +WORK_SRCS = work_thread.c work_queue.c work_cancel.c work_signal.c +endif + +ifeq ($(CONFIG_PAGING),y) +PGFILL_SRCS = pg_miss.c pg_worker.c +endif + +IRQ_SRCS = irq_initialize.c irq_attach.c irq_dispatch.c irq_unexpectedisr.c + +KMM_SRCS = kmm_initialize.c kmm_addregion.c kmm_semaphore.c \ + kmm_kmalloc.c kmm_kzalloc.c kmm_krealloc.c kmm_kfree.c + +CSRCS = $(MISC_SRCS) $(TSK_SRCS) $(SCHED_SRCS) $(WDOG_SRCS) $(TIME_SRCS) \ + $(SEM_SRCS) $(TIMER_SRCS) $(WORK_SRCS) $(PGFILL_SRCS) $(IRQ_SRCS) + +ifneq ($(CONFIG_DISABLE_CLOCK),y) +CSRCS += $(CLOCK_SRCS) +endif + +ifneq ($(CONFIG_DISABLE_PTHREAD),y) +CSRCS += $(PTHREAD_SRCS) +endif + +ifneq ($(CONFIG_DISABLE_SIGNALS),y) +CSRCS += $(SIGNAL_SRCS) +endif + +ifneq ($(CONFIG_DISABLE_MQUEUE),y) +CSRCS += $(MQUEUE_SRCS) +endif + +ifneq ($(CONFIG_DISABLE_ENVIRON),y) +CSRCS += $(ENV_SRCS) +endif + +ifeq ($(CONFIG_NUTTX_KERNEL),y) +CSRCS += $(KMM_SRCS) +endif + +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +BIN = libsched$(LIBEXT) + +all: $(BIN) + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +$(BIN): $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $@, $${obj}); \ + done ; ) + +.depend: Makefile $(SRCS) + @$(MKDEP) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +clean: + @rm -f $(BIN) *~ .*.swp + $(call CLEAN) + +distclean: clean + @rm -f Make.dep .depend + +-include Make.dep diff --git a/nuttx/sched/atexit.c b/nuttx/sched/atexit.c new file mode 100644 index 000000000..f7d81bec2 --- /dev/null +++ b/nuttx/sched/atexit.c @@ -0,0 +1,162 @@ +/**************************************************************************** + * sched/atexit.c + * + * Copyright (C) 2007, 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include + +#include + +#include "os_internal.h" + +#ifdef CONFIG_SCHED_ATEXIT + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: atexit + * + * Description: + * Registers a function to be called at program exit. + * The atexit() function registers the given function to be called + * at normal process termination, whether via exit or via return from + * the program's main(). + * + * NOTE: CONFIG_SCHED_ATEXIT must be defined to enable this function + * + * Limitiations in the current implementation: + * + * 1. Only a single atexit function can be registered unless + * CONFIG_SCHED_ATEXIT_MAX defines a larger number. + * 2. atexit functions are not inherited when a new task is + * created. + * + * Parameters: + * func - A pointer to the function to be called when the task exits. + * + * Return Value: + * Zero on success. Non-zero on failure. + * + ****************************************************************************/ + +int atexit(void (*func)(void)) +{ +#if defined(CONFIG_SCHED_ATEXIT_MAX) && CONFIG_SCHED_ATEXIT_MAX > 1 + _TCB *tcb = (_TCB*)g_readytorun.head; + int index; + int ret = ERROR; + + /* The following must be atomic */ + + if (func) + { + sched_lock(); + + /* Search for the first available slot. atexit() functions are registered + * from lower to higher arry indices; they must be called in the reverse + * order of registration when task exists, i.e., from higher to lower + * indices. + */ + + available = -1; + for (index = 0; index < CONFIG_SCHED_ATEXIT_MAX; index++) + { + if (!tcb->atexitfunc[index]) + { + tcb->atexitfunc[index] = func; + ret = OK; + break; + } + } + + sched_unlock(); + } + + return ret; +#else + _TCB *tcb = (_TCB*)g_readytorun.head; + int ret = ERROR; + + /* The following must be atomic */ + + sched_lock(); + if (func && !tcb->atexitfunc) + { + tcb->atexitfunc = func; + ret = OK; + } + + sched_unlock(); + return ret; +#endif +} + +#endif /* CONFIG_SCHED_ATEXIT */ + + diff --git a/nuttx/sched/clock_abstime2ticks.c b/nuttx/sched/clock_abstime2ticks.c new file mode 100644 index 000000000..2d7f7f480 --- /dev/null +++ b/nuttx/sched/clock_abstime2ticks.c @@ -0,0 +1,126 @@ +/******************************************************************************** + * clock_abstime2ticks.c + * + * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include "clock_internal.h" + +/******************************************************************************** + * Definitions + ********************************************************************************/ + +/******************************************************************************** + * Private Type Declarations + ********************************************************************************/ + +/******************************************************************************** + * Global Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Functions + ********************************************************************************/ + +/******************************************************************************** + * Public Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: clock_abstime2ticks + * + * Description: + * Convert an absolute timespec delay to system timer ticks. + * + * Parameters: + * clockid - The timing source to use in the conversion + * reltime - Convert this absolue time to system clock ticks. + * ticks - Return the converted number of ticks here. + * + * Return Value: + * OK on success; A non-zero error number on failure; + * + * Assumptions: + * Interrupts should be disabled so that the time is not changing during the + * calculation + * + ********************************************************************************/ + +int clock_abstime2ticks(clockid_t clockid, FAR const struct timespec *abstime, + FAR int *ticks) +{ + struct timespec currtime; + struct timespec reltime; + int ret; + + /* Convert the timespec to clock ticks. NOTE: Here we use internal knowledge + * that CLOCK_REALTIME is defined to be zero! + */ + + ret = clock_gettime(clockid, &currtime); + if (ret) + { + return EINVAL; + } + + /* The relative time to wait is the absolute time minus the current time. */ + + reltime.tv_nsec = (abstime->tv_nsec - currtime.tv_nsec); + reltime.tv_sec = (abstime->tv_sec - currtime.tv_sec); + + /* Check if we were supposed to borrow from the seconds to borrow from the + * seconds + */ + + if (reltime.tv_nsec < 0) + { + reltime.tv_nsec += NSEC_PER_SEC; + reltime.tv_sec -= 1; + } + + /* Convert this relative time into microseconds.*/ + + return clock_time2ticks(&reltime, ticks); +} diff --git a/nuttx/sched/clock_dow.c b/nuttx/sched/clock_dow.c new file mode 100644 index 000000000..93bcfc2d9 --- /dev/null +++ b/nuttx/sched/clock_dow.c @@ -0,0 +1,88 @@ +/**************************************************************************** + * sched/clock_dow.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include + +#include + +#include "clock_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* 23 * (month + 1) / 9, month = 0..11 */ + +static const uint8_t g_lookup[12] = {2, 5, 7, 10, 12, 15, 17, 20, 23, 25, 28, 30}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: clock_dow + * + * Description: + * Calculate the day of week (DOW) from they year month and day. Based on + * an algorithm pubished in 1990 by Michael Keith and Tom Craver with some + * tweaks to handle months in the range 0-11. + * + * Parameters: + * year - year (e.g., 1988) + * month - 0 through 11 + * day - 1 through 31 + * + * Return Value: + * The day of the week as days since Sunday: 0 = Sunday, 1 = Monday, etc. + * + * Assumptions: + * + ****************************************************************************/ + +int clock_dow(int year, int month, int day) +{ + day += month < 2 ? year-- : year - 2; + return ((int)g_lookup[month] + day + 4 + year/4 - year/100 + year/400) % 7; +} diff --git a/nuttx/sched/clock_getres.c b/nuttx/sched/clock_getres.c new file mode 100644 index 000000000..a76b14ab6 --- /dev/null +++ b/nuttx/sched/clock_getres.c @@ -0,0 +1,121 @@ +/************************************************************************ + * sched/clock_getres.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include + +#include "clock_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/********************************************************************** + * Public Constant Data + **********************************************************************/ + +/************************************************************************ + * Public Variables + ************************************************************************/ + +/********************************************************************** + * Private Variables + **********************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: clock_getres + * + * Description: + * Clock Functions based on POSIX APIs + * + ************************************************************************/ + +int clock_getres(clockid_t clock_id, struct timespec *res) +{ + uint32_t time_res; + int ret = OK; + + sdbg("clock_id=%d\n", clock_id); + + /* Only CLOCK_REALTIME is supported */ + + if (clock_id != CLOCK_REALTIME) + { + sdbg("Returning ERROR\n"); + set_errno(EINVAL); + ret = ERROR; + } + else + { + /* Get the clock resolution in nanoseconds */ + + time_res = MSEC_PER_TICK * NSEC_PER_MSEC; + + /* And return this as a timespec. */ + + res->tv_sec = 0; + res->tv_nsec = time_res; + + sdbg("Returning res=(%d,%d) time_res=%d\n", + (int)res->tv_sec, (int)res->tv_nsec, + (int)time_res); + } + + return ret; +} diff --git a/nuttx/sched/clock_gettime.c b/nuttx/sched/clock_gettime.c new file mode 100644 index 000000000..d6772dada --- /dev/null +++ b/nuttx/sched/clock_gettime.c @@ -0,0 +1,180 @@ +/************************************************************************ + * sched/clock_gettime.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include + +#include +#include +#include +#include +#include + +#include + +#include "clock_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/********************************************************************** + * Public Constant Data + **********************************************************************/ + +/************************************************************************ + * Public Variables + ************************************************************************/ + +/********************************************************************** + * Private Variables + **********************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: clock_gettime + * + * Description: + * Clock Functions based on POSIX APIs + * + ************************************************************************/ + +int clock_gettime(clockid_t clock_id, struct timespec *tp) +{ +#ifdef CONFIG_SYSTEM_TIME64 + uint64_t msecs; + uint64_t secs; + uint64_t nsecs; +#else + uint32_t msecs; + uint32_t secs; + uint32_t nsecs; +#endif + int ret = OK; + + sdbg("clock_id=%d\n", clock_id); + DEBUGASSERT(tp != NULL); + + /* CLOCK_REALTIME - POSIX demands this to be present. This is the wall + * time clock. + */ + +#ifdef CONFIG_RTC + if (clock_id == CLOCK_REALTIME || clock_id == CLOCK_ACTIVETIME) +#else + if (clock_id == CLOCK_REALTIME) +#endif + { + /* Do we have a high-resolution RTC that can provie us with the time? */ + +#ifdef CONFIG_RTC_HIRES + if (g_rtc_enabled && clock_id != CLOCK_ACTIVETIME) + { + /* Yes.. Get the hi-resolution time from the RTC */ + + ret = up_rtc_gettime(tp); + } + else +#endif + { + /* Get the elapsed time since power up (in milliseconds) biased + * as appropriate. + */ + + msecs = MSEC_PER_TICK * (g_system_timer - g_tickbias); + + sdbg("msecs = %d g_tickbias=%d\n", + (int)msecs, (int)g_tickbias); + + /* Get the elapsed time in seconds and nanoseconds. */ + + secs = msecs / MSEC_PER_SEC; + nsecs = (msecs - (secs * MSEC_PER_SEC)) * NSEC_PER_MSEC; + + sdbg("secs = %d + %d nsecs = %d + %d\n", + (int)msecs, (int)g_basetime.tv_sec, + (int)nsecs, (int)g_basetime.tv_nsec); + + /* Add the base time to this. */ + + secs += (uint32_t)g_basetime.tv_sec; + nsecs += (uint32_t)g_basetime.tv_nsec; + + /* Handle carry to seconds. */ + + if (nsecs > NSEC_PER_SEC) + { + uint32_t dwCarrySecs = nsecs / NSEC_PER_SEC; + secs += dwCarrySecs; + nsecs -= (dwCarrySecs * NSEC_PER_SEC); + } + + /* And return the result to the caller. */ + + tp->tv_sec = (time_t)secs; + tp->tv_nsec = (long)nsecs; + } + + sdbg("Returning tp=(%d,%d)\n", (int)tp->tv_sec, (int)tp->tv_nsec); + } + else + { + sdbg("Returning ERROR\n"); + + errno = EINVAL; + ret = ERROR; + } + + return ret; +} diff --git a/nuttx/sched/clock_gettimeofday.c b/nuttx/sched/clock_gettimeofday.c new file mode 100644 index 000000000..6437ef955 --- /dev/null +++ b/nuttx/sched/clock_gettimeofday.c @@ -0,0 +1,113 @@ +/**************************************************************************** + * sched/clock_gettimeofday.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include + +#include "clock_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/************************************************************************** + * Public Constant Data + **************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/************************************************************************** + * Private Variables + **************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: gettimeofday + * + * Description: + * Get the current time + * + ****************************************************************************/ + +int gettimeofday(struct timeval *tp, void *tzp) +{ + struct timespec ts; + int ret; + +#ifdef CONFIG_DEBUG + if (!tp) + { + errno = EINVAL; + return ERROR; + } +#endif + + /* Let clock_gettime do most of the work */ + + ret = clock_gettime(CLOCK_REALTIME, &ts); + if (ret == OK) + { + /* Convert the struct timespec to a struct timeval */ + + tp->tv_sec = ts.tv_sec; + tp->tv_usec = ts.tv_nsec / NSEC_PER_USEC; + } + + return ret; +} diff --git a/nuttx/sched/clock_initialize.c b/nuttx/sched/clock_initialize.c new file mode 100644 index 000000000..2e146bb47 --- /dev/null +++ b/nuttx/sched/clock_initialize.c @@ -0,0 +1,270 @@ +/**************************************************************************** + * sched/clock_initialize.c + * + * Copyright (C) 2007, 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include + +#include +#include +#include +#include + +#ifdef CONFIG_RTC +# include +#endif + +#include +#include +#include + +#include "clock_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ +/* Standard time definitions (in units of seconds) */ + +#define SEC_PER_MIN ((time_t)60) +#define SEC_PER_HOUR ((time_t)60 * SEC_PER_MIN) +#define SEC_PER_DAY ((time_t)24 * SEC_PER_HOUR) + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/************************************************************************** + * Public Constant Data + **************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +#ifdef CONFIG_SYSTEM_TIME64 +volatile uint64_t g_system_timer; +uint64_t g_tickbias; +#else +volatile uint32_t g_system_timer; +uint32_t g_tickbias; +#endif + +struct timespec g_basetime; + +/************************************************************************** + * Private Variables + **************************************************************************/ + +/************************************************************************** + * Private Functions + **************************************************************************/ + +/**************************************************************************** + * Name: clock_basetime + * + * Description: + * Get the initial time value from the best source available. + * + ****************************************************************************/ + +#ifdef CONFIG_RTC +#if defined(CONFIG_RTC_DATETIME) +/* Initialize the system time using a broken out date/time structure */ + +static inline void clock_basetime(FAR struct timespec *tp) +{ + struct tm rtctime; + + /* Get the broken-out time from the date/time RTC. */ + + (void)up_rtc_getdatetime(&rtctime); + + /* And use the broken-out time to initialize the system time */ + + tp->tv_sec = mktime(&rtctime); + tp->tv_nsec = 0; +} + +#elif defined(CONFIG_RTC_HIRES) + +/* Initialize the system time using a high-resolution structure */ + +static inline void clock_basetime(FAR struct timespec *tp) +{ + /* Get the complete time from the hi-res RTC. */ + + (void)up_rtc_gettime(tp); +} + +#else + +/* Initialize the system time using seconds only */ + +static inline void clock_basetime(FAR struct timespec *tp) +{ + /* Get the seconds (only) from the lo-resolution RTC */ + + tp->tv_sec = up_rtc_time(); + tp->tv_nsec = 0; +} + +#endif /* CONFIG_RTC_HIRES */ +#else /* CONFIG_RTC */ + +static inline void clock_basetime(FAR struct timespec *tp) +{ + time_t jdn = 0; + + /* Get the EPOCH-relative julian date from the calendar year, + * month, and date + */ + + jdn = clock_calendar2utc(CONFIG_START_YEAR, CONFIG_START_MONTH, + CONFIG_START_DAY); + + /* Set the base time as seconds into this julian day. */ + + tp->tv_sec = jdn * SEC_PER_DAY; + tp->tv_nsec = 0; +} + +#endif /* CONFIG_RTC */ + +/**************************************************************************** + * Name: clock_inittime + * + * Description: + * Get the initial time value from the best source available. + * + ****************************************************************************/ + +static void clock_inittime(void) +{ + /* (Re-)initialize the time value to match the RTC*/ + + clock_basetime(&g_basetime); + g_system_timer = 0; + g_tickbias = 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: clock_initialize + * + * Description: + * Perform one-time initialization of the timing facilities. + * + ****************************************************************************/ + +void clock_initialize(void) +{ + /* Initialize the RTC hardware */ + +#ifdef CONFIG_RTC + up_rtcinitialize(); +#endif + + /* Initialize the time value to match the RTC */ + + clock_inittime(); +} + +/**************************************************************************** + * Name: clock_synchronize + * + * Description: + * Synchronize the system timer to a hardware RTC. This operation is + * normally performed automatically by the system during clock + * initialization. However, the user may also need to explicitly re- + * synchronize the system timer to the RTC under certain conditions where + * the system timer is known to be in error. For example, in certain low- + * power states, the system timer may be stopped but the RTC will continue + * keep correct time. After recovering from such low-power state, this + * function should be called to restore the correct system time. + * + * Calling this function could result in system time going "backward" in + * time, especially with certain lower resolution RTC implementations. + * Time going backward could have bad consequences if there are ongoing + * timers and delays. So use this interface with care. + * + * Parameters: + * None + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_RTC +void clock_synchronize(void) +{ + irqstate_t flags; + + /* Re-initialize the time value to match the RTC */ + + flags = irqsave(); + clock_inittime(); + irqrestore(flags); +} +#endif + +/**************************************************************************** + * Name: clock_timer + * + * Description: + * This function must be called once every time the real time clock + * interrupt occurs. The interval of this clock interrupt must be + * MSEC_PER_TICK + * + ****************************************************************************/ + +void clock_timer(void) +{ + /* Increment the per-tick system counter */ + + g_system_timer++; +} diff --git a/nuttx/sched/clock_internal.h b/nuttx/sched/clock_internal.h new file mode 100644 index 000000000..aba9723b6 --- /dev/null +++ b/nuttx/sched/clock_internal.h @@ -0,0 +1,91 @@ +/******************************************************************************** + * sched/clock_internal.h + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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. + * + ********************************************************************************/ + +#ifndef __SCHED_CLOCK_INTERNAL_H +#define __SCHED_CLOCK_INTERNAL_H + +/******************************************************************************** + * Included Files + ********************************************************************************/ + +#include + +#include + +#include +#include + +/******************************************************************************** + * Pre-processor Definitions + ********************************************************************************/ +/* Configuration ************************************************************/ +/* If CONFIG_SYSTEM_TIME64 is selected and the CPU supports long long types, + * then a 64-bit system time will be used. + */ + +#ifndef CONFIG_HAVE_LONG_LONG +# undef CONFIG_SYSTEM_TIME64 +#endif + +/******************************************************************************** + * Public Type Definitions + ********************************************************************************/ + +/******************************************************************************** + * Global Variables + ********************************************************************************/ + +#ifdef CONFIG_SYSTEM_TIME64 +extern uint64_t g_tickbias; +#else +extern uint32_t g_tickbias; +#endif + +extern struct timespec g_basetime; + +/******************************************************************************** + * Public Function Prototypes + ********************************************************************************/ + +void weak_function clock_initialize(void); +void weak_function clock_timer(void); + +int clock_abstime2ticks(clockid_t clockid, + FAR const struct timespec *abstime, + FAR int *ticks); +int clock_time2ticks(FAR const struct timespec *reltime, FAR int *ticks); +int clock_ticks2time(int ticks, FAR struct timespec *reltime); + +#endif /* __SCHED_CLOCK_INTERNAL_H */ diff --git a/nuttx/sched/clock_settime.c b/nuttx/sched/clock_settime.c new file mode 100644 index 000000000..ce809aa11 --- /dev/null +++ b/nuttx/sched/clock_settime.c @@ -0,0 +1,149 @@ +/************************************************************************ + * sched/clock_settime.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include + +#include +#include +#include +#include + +#include +#include "clock_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/********************************************************************** + * Public Constant Data + **********************************************************************/ + +/************************************************************************ + * Public Variables + ************************************************************************/ + +/********************************************************************** + * Private Variables + **********************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: clock_settime + * + * Description: + * Clock Functions based on POSIX APIs + * + ************************************************************************/ + +int clock_settime(clockid_t clock_id, FAR const struct timespec *tp) +{ + irqstate_t flags; + int ret = OK; + + sdbg("clock_id=%d\n", clock_id); + DEBUGASSERT(tp != NULL); + + /* CLOCK_REALTIME - POSIX demands this to be present. This is the wall + * time clock. + */ + +#ifdef CONFIG_RTC + if (clock_id == CLOCK_REALTIME || clock_id == CLOCK_ACTIVETIME) +#else + if (clock_id == CLOCK_REALTIME) +#endif + { + /* Interrupts are disabled here so that the in-memory time + * representation and the RTC setting will be as close as + * possible. + */ + + flags = irqsave(); + + /* Save the new base time. */ + + g_basetime.tv_sec = tp->tv_sec; + g_basetime.tv_nsec = tp->tv_nsec; + + /* Get the elapsed time since power up (in milliseconds) biased + * as appropriate. + */ + + g_tickbias = g_system_timer; + + /* Setup the RTC (lo- or high-res) */ + +#ifdef CONFIG_RTC + if (g_rtc_enabled && clock_id != CLOCK_ACTIVETIME) + { + up_rtc_settime(tp); + } +#endif + irqrestore(flags); + + sdbg("basetime=(%d,%d) tickbias=%d\n", + (int)g_basetime.tv_sec, (int)g_basetime.tv_nsec, + (int)g_tickbias); + } + else + { + sdbg("Returning ERROR\n"); + set_errno(EINVAL); + ret = ERROR; + } + + return ret; +} diff --git a/nuttx/sched/clock_systimer.c b/nuttx/sched/clock_systimer.c new file mode 100644 index 000000000..33c16db94 --- /dev/null +++ b/nuttx/sched/clock_systimer.c @@ -0,0 +1,110 @@ +/**************************************************************************** + * sched/clock_systimer.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include + +#include + +#include "clock_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: clock_systimer + * + * Description: + * Return the current value of the 32-bit system timer counter + * + * Parameters: + * None + * + * Return Value: + * The current value of the system timer counter + * + * Assumptions: + * + ****************************************************************************/ + +#if !defined(clock_systimer) /* See nuttx/clock.h */ +uint32_t clock_systimer(void) +{ +#ifdef CONFIG_SYSTEM_TIME64 + return (uint32_t)(g_system_timer & 0x00000000ffffffff); +#else + return g_system_timer; +#endif +} +#endif + +/**************************************************************************** + * Name: clock_systimer64 + * + * Description: + * Return the current value of the 64-bit system timer counter + * + * Parameters: + * None + * + * Return Value: + * The current value of the system timer counter + * + * Assumptions: + * + ****************************************************************************/ + +#if !defined(clock_systimer) /* See nuttx/clock.h */ +#ifdef CONFIG_SYSTEM_TIME64 +uint64_t clock_systimer64(void) +{ + return g_system_timer; +} +#endif +#endif diff --git a/nuttx/sched/clock_ticks2time.c b/nuttx/sched/clock_ticks2time.c new file mode 100644 index 000000000..fd300692d --- /dev/null +++ b/nuttx/sched/clock_ticks2time.c @@ -0,0 +1,94 @@ +/******************************************************************************** + * clock_ticks2time.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include "clock_internal.h" + +/******************************************************************************** + * Definitions + ********************************************************************************/ + +/******************************************************************************** + * Private Type Declarations + ********************************************************************************/ + +/******************************************************************************** + * Global Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Functions + ********************************************************************************/ + +/******************************************************************************** + * Public Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: clock_ticks2time + * + * Description: + * Convert the system time tick value to a relative time. + * + * Parameters: + * ticks - The number of system time ticks to convert. + * reltime - Return the converted system time here. + * + * Return Value: + * Always returns OK + * + * Assumptions: + * + ********************************************************************************/ + +int clock_ticks2time(int ticks, FAR struct timespec *reltime) +{ + int remainder; + + reltime->tv_sec = ticks / TICK_PER_SEC; + remainder = ticks - TICK_PER_SEC * reltime->tv_sec; + reltime->tv_nsec = remainder * NSEC_PER_TICK; + return OK; +} diff --git a/nuttx/sched/clock_time2ticks.c b/nuttx/sched/clock_time2ticks.c new file mode 100644 index 000000000..383264d51 --- /dev/null +++ b/nuttx/sched/clock_time2ticks.c @@ -0,0 +1,102 @@ +/******************************************************************************** + * sched/clock_time2ticks.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include + +#include "clock_internal.h" + +/******************************************************************************** + * Definitions + ********************************************************************************/ + +/******************************************************************************** + * Private Type Declarations + ********************************************************************************/ + +/******************************************************************************** + * Global Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Functions + ********************************************************************************/ + +/******************************************************************************** + * Public Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: clock_time2ticks + * + * Description: + * Convert a timespec delay to system timer ticks. This function is suitable + * for calculating relative time delays and does not depend on the other + * clock_* logic. + * + * Parameters: + * reltime - Convert this relative time to system clock ticks. + * ticks - Return the converted number of ticks here. + * + * Return Value: + * Always returns OK + * + * Assumptions: + * + ********************************************************************************/ + +int clock_time2ticks(FAR const struct timespec *reltime, FAR int *ticks) +{ + int32_t relusec; + + /* Convert the relative time into microseconds.*/ + + relusec = reltime->tv_sec * USEC_PER_SEC + reltime->tv_nsec / NSEC_PER_USEC; + + /* Convert microseconds to clock ticks */ + + *ticks = relusec / USEC_PER_TICK; + return OK; +} diff --git a/nuttx/sched/env_clearenv.c b/nuttx/sched/env_clearenv.c new file mode 100644 index 000000000..7fe97a911 --- /dev/null +++ b/nuttx/sched/env_clearenv.c @@ -0,0 +1,83 @@ +/**************************************************************************** + * sched/env_clearenv.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#ifndef CONFIG_DISABLE_ENVIRON + +#include +#include +#include "os_internal.h" +#include "env_internal.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: clearenv + * + * Description: + * The clearenv() function clears the environment of all name-value pairs + * and sets the value of the external variable environ to NULL. + * + * Parameters: + * None + * + * Return Value: + * None + * + * Assumptions: + * Not called from an interrupt handler + * + ****************************************************************************/ + +int clearenv(void) +{ + return env_release((FAR _TCB*)g_readytorun.head); +} + +#endif /* CONFIG_DISABLE_ENVIRON */ + + + diff --git a/nuttx/sched/env_dup.c b/nuttx/sched/env_dup.c new file mode 100644 index 000000000..033348411 --- /dev/null +++ b/nuttx/sched/env_dup.c @@ -0,0 +1,132 @@ +/**************************************************************************** + * sched/env_dup.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#ifndef CONFIG_DISABLE_ENVIRON + +#include +#include +#include +#include + +#include + +#include "os_internal.h" +#include "env_internal.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: env_dup + * + * Description: + * Copy the internal environment structure of a task. This is the action + * that is performed when a new task is created: The new task has a private, + * exact duplicate of the parent task's environment. + * + * Parameters: + * ptcb The tcb to receive the newly allocated copy of the parspecifiedent + * TCB's environment structure with reference count equal to one + * + * Return Value: + * zero on success + * + * Assumptions: + * Not called from an interrupt handler. + * + ****************************************************************************/ + +int env_dup(FAR _TCB *ptcb) +{ + int ret = OK; + if (!ptcb ) + { + ret = -EINVAL; + } + else + { + FAR _TCB *parent = (FAR _TCB*)g_readytorun.head; + environ_t *envp = NULL; + + /* Pre-emption must be disabled throughout the following because the + * environment may be shared. + */ + + sched_lock(); + + /* Does the parent task have an environment? */ + + if (parent->envp) + { + /* Yes..The parent task has an environment, duplicate it */ + + size_t envlen = parent->envp->ev_alloc; + envp = (environ_t*)kmalloc(SIZEOF_ENVIRON_T( envlen )); + if (!envp) + { + ret = -ENOMEM; + } + else + { + envp->ev_crefs = 1; + envp->ev_alloc = envlen; + memcpy( envp->ev_env, parent->envp->ev_env, envlen ); + } + } + + /* Save the cloned environment in the new TCB */ + + ptcb->envp = envp; + sched_unlock(); + } + + return ret; +} + +#endif /* CONFIG_DISABLE_ENVIRON */ + + + diff --git a/nuttx/sched/env_dupenv.c b/nuttx/sched/env_dupenv.c new file mode 100644 index 000000000..32bf6a433 --- /dev/null +++ b/nuttx/sched/env_dupenv.c @@ -0,0 +1,112 @@ +/**************************************************************************** + * eched/env_dupenv.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#ifndef CONFIG_DISABLE_ENVIRON + +#include +#include + +#include + +#include "os_internal.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: dupenv + * + * Description: + * Copy the internal environment structure of a task. This is the action + * that is performed when a new task is created: The new task has a private, + * exact duplicate of the parent task's environment. + * + * Parameters: + * None + * + * Return Value: + * A pointer to a newly allocated copy of the specified TCB's environment + * structure with reference count equal to one. + * + * Assumptions: + * Not called from an interrupt handler. + * + ****************************************************************************/ + +FAR environ_t *dupenv(FAR _TCB *ptcb) +{ + environ_t *envp = NULL; + + /* Pre-emption must be disabled throughout the following because the + * environment may be shared. + */ + + sched_lock(); + + /* Does the parent task have an environment? */ + + if (ptcb->envp) + { + /* Yes..The parent task has an environment, duplicate it */ + + size_t envlen = ptcb->envp->ev_alloc + envp = (environ_t*)kmalloc(SIZEOF_ENVIRON_T( envlen )); + if (envp) + { + envp->ev_crefs = 1; + envp->ev_alloc = envlen; + memcmp( envp->ev_env, ptcb->envp->ev_env, envlen ); + } + } + + sched_unlock(); + return envp; +} + +#endif /* CONFIG_DISABLE_ENVIRON */ + + + diff --git a/nuttx/sched/env_findvar.c b/nuttx/sched/env_findvar.c new file mode 100644 index 000000000..a8e94180c --- /dev/null +++ b/nuttx/sched/env_findvar.c @@ -0,0 +1,131 @@ +/**************************************************************************** + * sched/env_findvar.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#ifndef CONFIG_DISABLE_ENVIRON + +#include +#include +#include + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: env_cmpname + ****************************************************************************/ + +static bool env_cmpname(const char *pszname, const char *peqname) +{ + /* Search until we find anything different in the two names */ + + for (; *pszname == *peqname; pszname++, peqname++); + + /* On sucess, pszname will end with '\0' and peqname with '=' */ + + if ( *pszname == '\0' && *peqname == '=' ) + { + return true; + } + + return false; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: env_findvar + * + * Description: + * Search the provided environment structure for the variable of the + * specified name. + * + * Parameters: + * envp The environment structre to be searched. + * pname The variable name to find + * + * Return Value: + * A pointer to the name=value string in the environment + * + * Assumptions: + * - Not called from an interrupt handler + * - Pre-emptions is disabled by caller + * + ****************************************************************************/ + +FAR char *env_findvar(environ_t *envp, const char *pname) +{ + char *ret = NULL; + + /* Verify input parameters */ + + if (envp && pname) + { + char *ptr; + char *end = &envp->ev_env[envp->ev_alloc]; + + /* Search for a name=value string with matching name */ + + for (ptr = envp->ev_env; + ptr < end && !env_cmpname( pname, ptr); + ptr += (strlen(ptr) + 1)); + + /* Check for success */ + + if (ptr < end) + { + ret = ptr; + } + } + + return ret; +} + +#endif /* CONFIG_DISABLE_ENVIRON */ + + + diff --git a/nuttx/sched/env_getenv.c b/nuttx/sched/env_getenv.c new file mode 100644 index 000000000..ee8d798b1 --- /dev/null +++ b/nuttx/sched/env_getenv.c @@ -0,0 +1,135 @@ +/**************************************************************************** + * env_getenv.c + * + * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#ifndef CONFIG_DISABLE_ENVIRON + +#include +#include +#include +#include + +#include "os_internal.h" +#include "env_internal.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: getenv + * + * Description: + * The getenv() function searches the environment list for a string that + * matches the string pointed to by name. + * + * Parameters: + * name - The name of the variable to find. + * + * Return Value: + * The value of the valiable (read-only) or NULL on failure + * + * Assumptions: + * Not called from an interrupt handler + * + ****************************************************************************/ + +FAR char *getenv(const char *name) +{ + FAR _TCB *rtcb; + FAR environ_t *envp; + FAR char *pvar; + FAR char *pvalue = NULL; + int ret = OK; + + /* Verify that a string was passed */ + + if (!name) + { + ret = EINVAL; + goto errout; + } + + /* Get a reference to the thread-private environ in the TCB.*/ + + sched_lock(); + rtcb = (FAR _TCB*)g_readytorun.head; + envp = rtcb->envp; + + /* Check if the variable exists */ + + if ( !envp || (pvar = env_findvar(envp, name)) == NULL) + { + ret = ENOENT; + goto errout_with_lock; + } + + /* It does! Get the value sub-string from the name=value string */ + + pvalue = strchr(pvar, '='); + if (!pvalue) + { + /* The name=value string has no '=' This is a bug! */ + + ret = EINVAL; + goto errout_with_lock; + } + + /* Adjust the pointer so that it points to the value right after the '=' */ + + pvalue++; + sched_unlock(); + return pvalue; + +errout_with_lock: + sched_unlock(); +errout: + set_errno(ret); + return NULL; +} + +#endif /* CONFIG_DISABLE_ENVIRON */ + + + diff --git a/nuttx/sched/env_getenvironptr.c b/nuttx/sched/env_getenvironptr.c new file mode 100644 index 000000000..25b09755b --- /dev/null +++ b/nuttx/sched/env_getenvironptr.c @@ -0,0 +1,104 @@ +/**************************************************************************** + * env_getenvironptr.c + * + * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#ifndef CONFIG_DISABLE_ENVIRON + +#include +#include +#include "os_internal.h" + +#undef get_environ_ptr + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: get_environ_ptr + * + * Description: + * Return a pointer to the thread specific environ variable. + * + * Parameters: + * None + * + * Return Value: + * A pointer to the per-thread environ variable. + * + * Assumptions: + * + ****************************************************************************/ + +FAR char **get_environ_ptr( void ) +{ +#if 1 + + /* Type of internal representation of environment is incompatible with + * char ** return value. + */ + + return NULL; + +#else + + /* Return a reference to the thread-private environ in the TCB.*/ + + FAR _TCB *ptcb = (FAR _TCB*)g_readytorun.head; + if (ptcb->envp) + { + return &ptcb->envp->ev_env; + } + else + { + return NULL; + } + +#endif +} + +#endif /* CONFIG_DISABLE_ENVIRON */ + + + diff --git a/nuttx/sched/env_internal.h b/nuttx/sched/env_internal.h new file mode 100644 index 000000000..a6205d658 --- /dev/null +++ b/nuttx/sched/env_internal.h @@ -0,0 +1,95 @@ +/**************************************************************************** + * sched/env_internal.h + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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. + * + ****************************************************************************/ + +#ifndef __SCHED_ENV_INTERNAL_H +#define __SCHED_ENV_INTERNAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include "os_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#ifdef CONFIG_DISABLE_ENVIRON +# define env_dup(ptcb) (0) +# define env_share(ptcb) (0) +# define env_release(ptcb) (0) +#endif + +/**************************************************************************** + * Public Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +#ifndef CONFIG_DISABLE_ENVIRON +/* functions used by the task/pthread creation and destruction logic */ + +EXTERN int env_dup(FAR _TCB *ptcb); +EXTERN int env_share(FAR _TCB *ptcb); +EXTERN int env_release(FAR _TCB *ptcb); + +/* functions used internally the environment handling logic */ + +EXTERN FAR char *env_findvar(environ_t *envp, const char *pname); +EXTERN int env_removevar(environ_t *envp, char *pvar); +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __SCHED_ENV_INTERNAL_H */ + diff --git a/nuttx/sched/env_putenv.c b/nuttx/sched/env_putenv.c new file mode 100644 index 000000000..ad00dd13d --- /dev/null +++ b/nuttx/sched/env_putenv.c @@ -0,0 +1,123 @@ +/**************************************************************************** + * sched/env_putenv.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#ifndef CONFIG_DISABLE_ENVIRON + +#include +#include +#include +#include + +#include + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: putenv + * + * Description: + * The putenv() function adds or changes the value of environment variables. + * The argument string is of the form name=value. If name does not already + * exist in the environment, then string is added to the environment. If + * name does exist, then the value of name in the environment is changed to + * value. + * + * Parameters: + * name=value string describing the environment setting to add/modify + * + * Return Value: + * Zero on sucess + * + * Assumptions: + * Not called from an interrupt handler + * + ****************************************************************************/ + +int putenv(FAR const char *string) +{ + char *pname; + char *pequal; + int ret = OK; + + /* Verify that a string was passed */ + + if (!string) + { + ret = EINVAL; + goto errout; + } + + /* Parse the name=value string */ + + pname = strdup(string); + if (!pname) + { + ret = ENOMEM; + goto errout; + } + + pequal = strchr( pname, '='); + if (pequal) + { + /* Then let setenv do all of the work */ + + *pequal = '\0'; + ret = setenv(pname, pequal+1, TRUE); + } + + kfree(pname); + return ret; + +errout: + errno = ret; + return ERROR; +} + +#endif /* CONFIG_DISABLE_ENVIRON */ + + + diff --git a/nuttx/sched/env_release.c b/nuttx/sched/env_release.c new file mode 100644 index 000000000..83e65dbb5 --- /dev/null +++ b/nuttx/sched/env_release.c @@ -0,0 +1,125 @@ +/**************************************************************************** + * sched/env_clearenv.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#ifndef CONFIG_DISABLE_ENVIRON + +#include +#include +#include "os_internal.h" +#include "env_internal.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: env_release + * + * Description: + * The env_release() function clears the environment of all name-value + * pairs and sets the value of the external variable environ to NULL. + * + * Parameters: + * ptcb Identifies the TCB containing the environment structure + * + * Return Value: + * zero on success + * + * Assumptions: + * Not called from an interrupt handler + * + ****************************************************************************/ + +int env_release(FAR _TCB *ptcb) +{ + int ret = OK; + + if (!ptcb) + { + ret = -EINVAL; + } + else + { + FAR environ_t *envp; + + /* Examine the environ data in the TCB. Preemption is disabled because the + * the environment could be shared among threads. + */ + + sched_lock(); + envp = ptcb->envp; + if (ptcb->envp) + { + /* Check the reference count on the environment structure */ + + if ( envp->ev_crefs <= 1) + { + /* Decrementing the reference count will destroy the environment */ + + sched_free( envp ); /* plain free() should be fine here */ + } + else + { + /* The environment will persist after decrementing the reference + * count */ + + envp->ev_crefs--; + } + + /* In any case, the environment is no longer accessible on this thread */ + + ptcb->envp = NULL; + } + + sched_unlock(); + } + + return ret; +} + +#endif /* CONFIG_DISABLE_ENVIRON */ + + + diff --git a/nuttx/sched/env_removevar.c b/nuttx/sched/env_removevar.c new file mode 100644 index 000000000..e96aa7a37 --- /dev/null +++ b/nuttx/sched/env_removevar.c @@ -0,0 +1,119 @@ +/**************************************************************************** + * sched/env_removevar.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#ifndef CONFIG_DISABLE_ENVIRON + +#include +#include + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: env_removevar + * + * Description: + * Remove the referenced name=value pair from the environment + * + * Parameters: + * envp The environment containing the name=value pair + * pvar A pointer to the name=value pair in the restroom + * + * Return Value: + * Zero on success + * + * Assumptions: + * - Not called from an interrupt handler + * - Caller has pre-emptions disabled + * - Caller will reallocate the environment structure to the correct size + * + ****************************************************************************/ + +int env_removevar(environ_t *envp, char *pvar) +{ + int ret = ERROR; + if (envp && pvar) + { + /* Verify that the pointer lies within the environment region */ + + int alloc = envp->ev_alloc; /* Size of the allocated environment */ + char *end = &envp->ev_env[alloc]; /* Pointer to the end+1 of the environment */ + + if (pvar >= envp->ev_env && pvar < end) + { + /* Set up for the removal */ + + int len = strlen(pvar) + 1; /* Length of name=value string to remove */ + char *src = &pvar[len]; /* Address of name=value string after */ + char *dest = pvar; /* Location to move the next string */ + int count = end - src; /* Number of bytes to move (might be zero) */ + + /* Move all of the environment strings after the removed one 'down.' + * this is inefficient, but robably not high duty. + */ + + while (count-- > 0) + { + *dest++ = *src++; + } + + /* Then set to the new allocation size. The caller is expected to + * call realloc at some point but we don't do that here because the + * caller may add more stuff to the environment. + */ + + envp->ev_alloc -= len; + ret = OK; + } + } + + return ret; +} + +#endif /* CONFIG_DISABLE_ENVIRON */ + + + diff --git a/nuttx/sched/env_setenv.c b/nuttx/sched/env_setenv.c new file mode 100644 index 000000000..c186241ef --- /dev/null +++ b/nuttx/sched/env_setenv.c @@ -0,0 +1,208 @@ +/**************************************************************************** + * sched/env_setenv.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#ifndef CONFIG_DISABLE_ENVIRON + +#include +#include +#include +#include +#include + +#include + +#include "os_internal.h" +#include "env_internal.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: setenv + * + * Description: + * The setenv() function adds the variable name to the environment with the + * specified 'value' if the varialbe 'name" does not exist. If the 'name' + * does exist in the environment, then its value is changed to 'value' if + * 'overwrite' is non-zero; if 'overwrite' is zero, then the value of name + * unaltered. + * + * Parameters: + * name - The name of the variable to change + * value - The new value of the variable + * overwrite - Replace any existing value if non-zero. + * + * Return Value: + * Zero on success + * + * Assumptions: + * Not called from an interrupt handler + * + ****************************************************************************/ + +int setenv(const char *name, const char *value, int overwrite) +{ + FAR _TCB *rtcb; + FAR environ_t *envp; + FAR char *pvar; + int varlen; + int ret = OK; + + /* Verify input parameter */ + + if (!name) + { + ret = EINVAL; + goto errout; + } + + /* if no value is provided, then this is the same as unsetenv (unless + * overwrite is false) + */ + + if (!value || *value == '\0') + { + /* If overwite is set then this is the same as unsetenv */ + + if (overwrite) + { + return unsetenv(name); + } + else + { + /* Otherwise, it is a request to remove a variable without altering it? */ + + return OK; + } + } + + /* Get a reference to the thread-private environ in the TCB.*/ + + sched_lock(); + rtcb = (FAR _TCB*)g_readytorun.head; + envp = rtcb->envp; + + /* Check if the variable alreay exists */ + + if ( envp && (pvar = env_findvar(envp, name)) != NULL) + { + /* It does! Do we have permission to overwrite the existing value? */ + + if (!overwrite) + { + /* No.. then just return success */ + + sched_unlock(); + return OK; + } + + /* Yes.. just remove the name=value pair from the environment. It will + * be added again below. Note that we are responsible for reallocating + * the environment buffer; this will happen below. + */ + + (void)env_removevar(envp, pvar); + } + + /* Get the size of the new name=value string. The +2 is for the '=' and for + * null terminator + */ + + varlen = strlen(name) + strlen(value) + 2; + + /* Then allocate or reallocate the environment buffer */ + + if (envp) + { + int alloc = envp->ev_alloc; + environ_t *tmp = (environ_t*)krealloc(envp, SIZEOF_ENVIRON_T(alloc + varlen)); + if (!tmp) + { + ret = ENOMEM; + goto errout_with_lock; + } + + envp = tmp; + envp->ev_alloc = alloc + varlen; + pvar = &envp->ev_env[alloc]; + } + else + { + envp = (environ_t*)kmalloc(SIZEOF_ENVIRON_T(varlen)); + if (!envp) + { + ret = ENOMEM; + goto errout_with_lock; + } + + envp->ev_crefs = 1; + envp->ev_alloc = varlen; + pvar = envp->ev_env; + } + + /* Now, put the new name=value string into the environment buffer */ + + sprintf(pvar, "%s=%s", name, value); + + /* Save the new environment pointer (it might have changed due to allocation or + * reallocation. + */ + + rtcb->envp = envp; + sched_unlock(); + return OK; + +errout_with_lock: + sched_unlock(); +errout: + errno = ret; + return ERROR; +} + +#endif /* CONFIG_DISABLE_ENVIRON */ + + + diff --git a/nuttx/sched/env_share.c b/nuttx/sched/env_share.c new file mode 100644 index 000000000..5f37a0219 --- /dev/null +++ b/nuttx/sched/env_share.c @@ -0,0 +1,117 @@ +/**************************************************************************** + * sched/env_share.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#ifndef CONFIG_DISABLE_ENVIRON + +#include +#include + +#include "os_internal.h" +#include "env_internal.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: env_share + * + * Description: + * Increment the reference count on the internal environment structure of + * a task. This is the action that is performed when a new pthread is + * created: The new pthread shares the environment with its parent. + * + * Parameters: + * ptcb The new TCB to receive the shared environment. + * + * Return Value: + * A pointer to a specified TCB's environment structure with an incremented + * reference count. + * + * Assumptions: + * Not called from an interrupt handler. + * + ****************************************************************************/ + +int env_share(FAR _TCB *ptcb) +{ + int ret = OK; + if (!ptcb) + { + ret = -EINVAL; + } + else + { + FAR _TCB *parent = (FAR _TCB*)g_readytorun.head; + environ_t *envp = parent->envp; + + /* Pre-emption must be disabled throughout the following because the + * environment is shared. + */ + + sched_lock(); + + /* Does the parent task have an environment? */ + + if (envp) + { + /* Yes.. increment the reference count on the environment */ + + envp->ev_crefs++; + } + + /* Then share the environment */ + + ptcb->envp = envp; + sched_unlock(); + } + + return ret; +} + +#endif /* CONFIG_DISABLE_ENVIRON */ + + + diff --git a/nuttx/sched/env_unsetenv.c b/nuttx/sched/env_unsetenv.c new file mode 100644 index 000000000..52469fac9 --- /dev/null +++ b/nuttx/sched/env_unsetenv.c @@ -0,0 +1,138 @@ +/**************************************************************************** + * sched/env_unsetenv.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#ifndef CONFIG_DISABLE_ENVIRON + +#include +#include +#include + +#include + +#include "os_internal.h" +#include "env_internal.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: unsetenv + * + * Description: + * The unsetenv() function deletes the variable name from the environment. + * + * Parameters: + * name - The name of the variable to delete + * + * Return Value: + * Zero on success + * + * Assumptions: + * Not called from an interrupt handler + * + ****************************************************************************/ + +int unsetenv(const char *name) +{ + FAR _TCB *rtcb; + FAR environ_t *envp; + FAR char *pvar; + int ret = OK; + + /* Verify input parameter */ + + if (!name) + { + ret = EINVAL; + goto errout; + } + + /* Get a reference to the thread-private environ in the TCB.*/ + + sched_lock(); + rtcb = (FAR _TCB*)g_readytorun.head; + envp = rtcb->envp; + + /* Check if the variable exists */ + + if ( envp && (pvar = env_findvar(envp, name)) != NULL) + { + int alloc; + environ_t *tmp; + + /* It does! Remove the name=value pair from the environment. */ + + (void)env_removevar(envp, pvar); + + /* Reallocate the new environment buffer */ + + alloc = envp->ev_alloc; + tmp = (environ_t*)krealloc(envp, SIZEOF_ENVIRON_T(alloc)); + if (!tmp) + { + ret = ENOMEM; + goto errout_with_lock; + } + + /* Save the new environment pointer (it might have changed due to reallocation. */ + + rtcb->envp = tmp; + } + + sched_unlock(); + return OK; + +errout_with_lock: + sched_unlock(); +errout: + errno = ret; + return ERROR; +} + +#endif /* CONFIG_DISABLE_ENVIRON */ + + + diff --git a/nuttx/sched/errno_get.c b/nuttx/sched/errno_get.c new file mode 100644 index 000000000..cac041f64 --- /dev/null +++ b/nuttx/sched/errno_get.c @@ -0,0 +1,84 @@ +/**************************************************************************** + * sched/errno_get.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#undef get_errno_ptr +#undef get_errno +#undef errno + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: get_errno + * + * Description: + * Return the value of the thread specific errno. This function is only + * intended to provide a mechanism for user-mode programs to get the + * thread-specific errno value. It is #define'd to the symbol errno in + * include/errno.h. + * + * Parameters: + * None + * + * Return Value: + * The current value of the thread specific errno. + * + * Assumptions: + * + ****************************************************************************/ + +int get_errno(void) +{ + return *get_errno_ptr(); +} + + diff --git a/nuttx/sched/errno_getptr.c b/nuttx/sched/errno_getptr.c new file mode 100644 index 000000000..0b27768da --- /dev/null +++ b/nuttx/sched/errno_getptr.c @@ -0,0 +1,117 @@ +/**************************************************************************** + * sched/errno_getptr.c + * + * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include +#include +#include +#include "os_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#undef get_errno_ptr +#undef errno + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static int g_irqerrno; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: get_errno_ptr + * + * Description: + * Return a pointer to the thread specific errno. + * + * Parameters: + * None + * + * Return Value: + * A pointer to the per-thread errno variable. + * + * Assumptions: + * + ****************************************************************************/ + +FAR int *get_errno_ptr(void) +{ + /* Check if this function was called from an interrupt handler. In that + * case, we have to do things a little differently to prevent the interrupt + * handler from modifying the tasks errno value. + */ + + if (!up_interrupt_context()) + { + /* We were called from the normal tasking context. Verify that the + * task at the head of the ready-to-run list is actually running. It + * may not be running during very brief times during context switching + * logic (see, for example, task_deletecurrent.c). + */ + + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + if (rtcb->task_state == TSTATE_TASK_RUNNING) + { + /* Yes.. the task is running normally. Return a reference to the + * thread-private errno in the TCB of the running task. + */ + + return &rtcb->pterrno; + } + } + + /* We were called either from (1) an interrupt handler or (2) from normally + * code but in an unhealthy state. In either event, do not permit access to + * the errno in the TCB of the task at the head of the ready-to-run list. + * Instead, use a separate errno just for interrupt handlers. Of course, this + * would have to change if we ever wanted to support nested interrupts or if + * we really cared about the stability of the errno during those "unhealthy + * states." + */ + + return &g_irqerrno; +} + + diff --git a/nuttx/sched/errno_set.c b/nuttx/sched/errno_set.c new file mode 100644 index 000000000..eda680b64 --- /dev/null +++ b/nuttx/sched/errno_set.c @@ -0,0 +1,83 @@ +/**************************************************************************** + * sched/errno_set.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#undef get_errno_ptr +#undef set_errno +#undef errno + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: set_errno + * + * Description: + * Set the value of the thread specific errno. This function is only + * intended to provide a mechanism for user-mode programs to set the + * thread-specific errno value. + * + * Parameters: + * errcode - The thread specific errno will be set to this error code value. + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +void set_errno(int errcode) +{ + *get_errno_ptr() = errcode; +} + + diff --git a/nuttx/sched/exit.c b/nuttx/sched/exit.c new file mode 100644 index 000000000..7e50c273c --- /dev/null +++ b/nuttx/sched/exit.c @@ -0,0 +1,108 @@ +/**************************************************************************** + * sched/exit.c + * + * Copyright (C) 2007-2008, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include + +#include + +#include "os_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: exit + * + * Description: + * The exit() function causes normal process termination and the value of + * status & 0377 to be returned to the parent. + * + * All functions registered with atexit() and on_exit() are called, in the + * reverse order of their registration. + * + * All open streams are flushed and closed. + * + ****************************************************************************/ + +void exit(int status) +{ + _TCB *tcb = (_TCB*)g_readytorun.head; + + /* Only the lower 8-bits of status are used */ + + status &= 0xff; + + /* Perform common task termination logic */ + + task_exithook(tcb, status); + + /* Then "really" exit. Only the lower 8 bits of the exit status are used. */ + + _exit(status); +} diff --git a/nuttx/sched/getpid.c b/nuttx/sched/getpid.c new file mode 100644 index 000000000..f41467d9f --- /dev/null +++ b/nuttx/sched/getpid.c @@ -0,0 +1,85 @@ +/************************************************************************ + * sched/getpid.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include +#include + +#include "os_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: getpid + * + * Description: + * Get the task ID of the currently executing task. + * + ************************************************************************/ + +pid_t getpid(void) +{ + /* Return the task ID from the TCB at the head of the + * ready-to-run task list + */ + + return ((FAR _TCB*)g_readytorun.head)->pid; +} diff --git a/nuttx/sched/irq_attach.c b/nuttx/sched/irq_attach.c new file mode 100644 index 000000000..3f27a0530 --- /dev/null +++ b/nuttx/sched/irq_attach.c @@ -0,0 +1,127 @@ +/**************************************************************************** + * sched/irq_attach.c + * + * Copyright (C) 2007-2008, 2010, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include + +#include "irq_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: irq_attach + * + * Description: + * Configure the IRQ subsystem so that IRQ number 'irq' is dispatched to + * 'isr' + * + ****************************************************************************/ + +int irq_attach(int irq, xcpt_t isr) +{ +#if NR_IRQS > 0 + int ret = ERROR; + + if ((unsigned)irq < NR_IRQS) + { + irqstate_t state; + + /* If the new ISR is NULL, then the ISR is being detached. + * In this case, disable the ISR and direct any interrupts + * to the unexpected interrupt handler. + */ + + state = irqsave(); + if (isr == NULL) + { + /* Disable the interrupt if we can before detaching it. We might + * not be able to do this if: (1) the device does not have a + * centralized interrupt controller (so up_disable_irq() is not + * supported). Or (2) if the device has different number for vector + * numbers and IRQ numbers (in that case, we don't know the correct + * IRQ number to use to disable the interrupt). In those cases, the + * code will just need to be careful that it disables all interrupt + * sources before detaching from the interrupt vector. + */ + +#if !defined(CONFIG_ARCH_NOINTC) && !defined(CONFIG_ARCH_VECNOTIRQ) + up_disable_irq(irq); +#endif + /* Detaching the ISR really means re-attaching it to the + * unexpected exception handler. + */ + + isr = irq_unexpected_isr; + } + + /* Save the new ISR in the table. */ + + g_irqvector[irq] = isr; + irqrestore(state); + ret = OK; + } + + return ret; +#else + return OK; +#endif +} diff --git a/nuttx/sched/irq_dispatch.c b/nuttx/sched/irq_dispatch.c new file mode 100644 index 000000000..1c39f59d1 --- /dev/null +++ b/nuttx/sched/irq_dispatch.c @@ -0,0 +1,105 @@ +/**************************************************************************** + * sched/irq_dispatch.c + * + * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include + +#include "irq_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: irq_dispatch + * + * Description: + * This function must be called from the achitecture-specific logic in + * order to dispatch an interrupt to the appropriate, registered handling + * logic. + * + ***************************************************************************/ + +void irq_dispatch(int irq, FAR void *context) +{ + xcpt_t vector; + + /* Perform some sanity checks */ + +#if NR_IRQS > 0 + if ((unsigned)irq >= NR_IRQS || g_irqvector[irq] == NULL) + { + vector = irq_unexpected_isr; + } + else + { + vector = g_irqvector[irq]; + } +#else + vector = irq_unexpected_isr; +#endif + + /* Then dispatch to the interrupt handler */ + + vector(irq, context); +} + diff --git a/nuttx/sched/irq_initialize.c b/nuttx/sched/irq_initialize.c new file mode 100644 index 000000000..2053dcb83 --- /dev/null +++ b/nuttx/sched/irq_initialize.c @@ -0,0 +1,91 @@ +/**************************************************************************** + * sched/irq_initialize.c + * + * Copyright (C) 2007-2008, 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include +#include + +#include "irq_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +FAR xcpt_t g_irqvector[NR_IRQS+1]; + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: irq_initialize + * + * Description: + * Configure the IRQ subsystem + * + ****************************************************************************/ + +void irq_initialize(void) +{ + int i; + + /* Point all interrupt vectors to the unexpected interrupt */ + + for (i = 0; i < NR_IRQS; i++) + { + g_irqvector[i] = irq_unexpected_isr; + } +} + diff --git a/nuttx/sched/irq_internal.h b/nuttx/sched/irq_internal.h new file mode 100644 index 000000000..28411f64f --- /dev/null +++ b/nuttx/sched/irq_internal.h @@ -0,0 +1,83 @@ +/**************************************************************************** + * sched/irq_internal.h + * + * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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. + * + ****************************************************************************/ + +#ifndef __SCHED_IRQ_INTERNAL_H +#define __SCHED_IRQ_INTERNAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Type Declarations + ****************************************************************************/ + +extern FAR xcpt_t g_irqvector[NR_IRQS+1]; + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +EXTERN void weak_function irq_initialize(void); +EXTERN int irq_unexpected_isr(int irq, FAR void *context); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __SCHED_IRQ_INTERNAL_H */ + diff --git a/nuttx/sched/irq_unexpectedisr.c b/nuttx/sched/irq_unexpectedisr.c new file mode 100644 index 000000000..c0090ead4 --- /dev/null +++ b/nuttx/sched/irq_unexpectedisr.c @@ -0,0 +1,88 @@ +/**************************************************************************** + * sched/irq_unexpectedisr.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include + +#include + +#include "os_internal.h" +#include "irq_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: irq_unexpected_isr + * + * Description: + * An interrupt has been received for an IRQ that was never registered + * with the system. + * + ****************************************************************************/ + +int irq_unexpected_isr(int irq, FAR void *context) +{ + (void)irqsave(); + lldbg("irq: %d\n", irq); + PANIC(OSERR_UNEXPECTEDISR); + return OK; /* Won't get here */ +} diff --git a/nuttx/sched/kmm_addregion.c b/nuttx/sched/kmm_addregion.c new file mode 100644 index 000000000..652367f5a --- /dev/null +++ b/nuttx/sched/kmm_addregion.c @@ -0,0 +1,113 @@ +/************************************************************************ + * sched/kmm_addregion.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include + +#ifdef CONFIG_NUTTX_KERNEL + +/* This logic is all tentatively and, hopefully, will grow in usability. + * For now, the kernel-mode build uses the memory manager that is + * provided in the user-space build. That is awkward but reasonable for + * the current level of support: At present, only memory protection is + * provided. Kernel-mode code may call into user-mode code, but not + * vice-versa. So hosting the memory manager in user-space allows the + * memory manager to be shared in both kernel- and user-mode spaces. + * + * In the longer run, if an MMU is support that can provide virtualized + * memory, then some SLAB memory manager will be required in kernel-space + * with some kind of brk() system call to obtain mapped heap space. + * + * In the current build model, the user-space module is built first. The + * file user_map.h is generated in the first pass and contains the + * addresses of the memory manager needed in this file: + */ + +#include + +/************************************************************************ + * Pre-processor definition + ************************************************************************/ + +/* This value is obtained from user_map.h */ + +#define KADDREGION(h,s) ((kmaddregion_t)CONFIG_USER_MMADDREGION)(h,s) + +/************************************************************************ + * Private Types + ************************************************************************/ + +typedef void (*kmaddregion_t)(FAR void*, size_t); + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: kmm_addregion + * + * Description: + * This is a simple redirection to the user-space mm_addregion() + * function. + * + * Parameters: + * heap_start - Address of the beginning of the memory region + * heap_size - The size (in bytes) if the memory region. + * + * Return Value: + * None + * + * Assumptions: + * 1. mm_addregion() resides in user-space + * 2. The address of the user space mm_addregion() is provided in + * user_map.h + * 3. The user-space mm_addregion() is callable from kernel-space. + * + ************************************************************************/ + +void kmm_addregion(FAR void *heap_start, size_t heap_size) +{ + return KADDREGION(heap_start, heap_size); +} + +#endif /* CONFIG_NUTTX_KERNEL */ diff --git a/nuttx/sched/kmm_initialize.c b/nuttx/sched/kmm_initialize.c new file mode 100644 index 000000000..6dd08951b --- /dev/null +++ b/nuttx/sched/kmm_initialize.c @@ -0,0 +1,113 @@ +/************************************************************************ + * sched/kmm_initialize.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include + +#ifdef CONFIG_NUTTX_KERNEL + +/* This logic is all tentatively and, hopefully, will grow in usability. + * For now, the kernel-mode build uses the memory manager that is + * provided in the user-space build. That is awkward but reasonable for + * the current level of support: At present, only memory protection is + * provided. Kernel-mode code may call into user-mode code, but not + * vice-versa. So hosting the memory manager in user-space allows the + * memory manager to be shared in both kernel- and user-mode spaces. + * + * In the longer run, if an MMU is support that can provide virtualized + * memory, then some SLAB memory manager will be required in kernel-space + * with some kind of brk() system call to obtain mapped heap space. + * + * In the current build model, the user-space module is built first. The + * file user_map.h is generated in the first pass and contains the + * addresses of the memory manager needed in this file: + */ + +#include + +/************************************************************************ + * Pre-processor definition + ************************************************************************/ + +/* This value is obtained from user_map.h */ + +#define KINITIALIZE(h,s) ((kminitialize_t)CONFIG_USER_MMINIT)(h,s) + +/************************************************************************ + * Private Types + ************************************************************************/ + +typedef void (*kminitialize_t)(FAR void*, size_t); + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: kmm_initialize + * + * Description: + * This is a simple redirection to the user-space mm_initialize() + * function. + * + * Parameters: + * heap_start - Address of the beginning of the (initial) memory region + * heap_size - The size (in bytes) if the (initial) memory region. + * + * Return Value: + * None + * + * Assumptions: + * 1. mm_initialize() resides in user-space + * 2. The address of the user space mm_initialize() is provided in + * user_map.h + * 3. The user-space mm_initialize() is callable from kernel-space. + * + ************************************************************************/ + +void kmm_initialize(FAR void *heap_start, size_t heap_size) +{ + return KINITIALIZE(heap_start, heap_size); +} + +#endif /* CONFIG_NUTTX_KERNEL */ diff --git a/nuttx/sched/kmm_kfree.c b/nuttx/sched/kmm_kfree.c new file mode 100644 index 000000000..0f0eaa6c2 --- /dev/null +++ b/nuttx/sched/kmm_kfree.c @@ -0,0 +1,110 @@ +/************************************************************************ + * sched/kmm_kfree.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include + +#ifdef CONFIG_NUTTX_KERNEL + +/* This logic is all tentatively and, hopefully, will grow in usability. + * For now, the kernel-mode build uses the memory manager that is + * provided in the user-space build. That is awkward but reasonable for + * the current level of support: At present, only memory protection is + * provided. Kernel-mode code may call into user-mode code, but not + * vice-versa. So hosting the memory manager in user-space allows the + * memory manager to be shared in both kernel- and user-mode spaces. + * + * In the longer run, if an MMU is support that can provide virtualized + * memory, then some SLAB memory manager will be required in kernel-space + * with some kind of brk() system call to obtain mapped heap space. + * + * In the current build model, the user-space module is built first. The + * file user_map.h is generated in the first pass and contains the + * addresses of the memory manager needed in this file: + */ + +#include + +/************************************************************************ + * Pre-processor definition + ************************************************************************/ + +/* This value is obtained from user_map.h */ + +#define KFREE(p) ((kfree_t)CONFIG_USER_FREE)(p) + +/************************************************************************ + * Private Types + ************************************************************************/ + +typedef void (*kfree_t)(FAR void *); + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: kfree + * + * Description: + * This is a simple redirection to the user-space free() function. + * + * Parameters: + * None + * + * Return Value: + * None + * + * Assumptions: + * 1. free() resides in user-space + * 2. The address of the user space free() is provided in user_map.h + * 3. The user-space free() is callable from kernel-space. + * + ************************************************************************/ + +void kfree(FAR void *mem) +{ + return KFREE(mem); +} + +#endif /* CONFIG_NUTTX_KERNEL */ diff --git a/nuttx/sched/kmm_kmalloc.c b/nuttx/sched/kmm_kmalloc.c new file mode 100644 index 000000000..5e34c157f --- /dev/null +++ b/nuttx/sched/kmm_kmalloc.c @@ -0,0 +1,110 @@ +/************************************************************************ + * sched/kmm_kmalloc.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include + +#ifdef CONFIG_NUTTX_KERNEL + +/* This logic is all tentatively and, hopefully, will grow in usability. + * For now, the kernel-mode build uses the memory manager that is + * provided in the user-space build. That is awkward but reasonable for + * the current level of support: At present, only memory protection is + * provided. Kernel-mode code may call into user-mode code, but not + * vice-versa. So hosting the memory manager in user-space allows the + * memory manager to be shared in both kernel- and user-mode spaces. + * + * In the longer run, if an MMU is support that can provide virtualized + * memory, then some SLAB memory manager will be required in kernel-space + * with some kind of brk() system call to obtain mapped heap space. + * + * In the current build model, the user-space module is built first. The + * file user_map.h is generated in the first pass and contains the + * addresses of the memory manager needed in this file: + */ + +#include + +/************************************************************************ + * Pre-processor definition + ************************************************************************/ + +/* This value is obtained from user_map.h */ + +#define KMALLOC(s) ((kmalloc_t)CONFIG_USER_MALLOC)(s) + +/************************************************************************ + * Private Types + ************************************************************************/ + +typedef FAR void *(*kmalloc_t)(size_t); + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: kmalloc + * + * Description: + * This is a simple redirection to the user-space malloc() function. + * + * Parameters: + * size - Size (in bytes) of the memory region to be allocated. + * + * Return Value: + * The address of the allocated memory (NULL on failure to allocate) + * + * Assumptions: + * 1. malloc() resides in user-space + * 2. The address of the user space malloc() is provided in user_map.h + * 3. The user-space malloc() is callable from kernel-space. + * + ************************************************************************/ + +FAR void *kmalloc(size_t size) +{ + return KMALLOC(size); +} + +#endif /* CONFIG_NUTTX_KERNEL */ diff --git a/nuttx/sched/kmm_krealloc.c b/nuttx/sched/kmm_krealloc.c new file mode 100644 index 000000000..3d3726566 --- /dev/null +++ b/nuttx/sched/kmm_krealloc.c @@ -0,0 +1,111 @@ +/************************************************************************ + * sched/kmm_krealloc.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include + +#ifdef CONFIG_NUTTX_KERNEL + +/* This logic is all tentatively and, hopefully, will grow in usability. + * For now, the kernel-mode build uses the memory manager that is + * provided in the user-space build. That is awkward but reasonable for + * the current level of support: At present, only memory protection is + * provided. Kernel-mode code may call into user-mode code, but not + * vice-versa. So hosting the memory manager in user-space allows the + * memory manager to be shared in both kernel- and user-mode spaces. + * + * In the longer run, if an MMU is support that can provide virtualized + * memory, then some SLAB memory manager will be required in kernel-space + * with some kind of brk() system call to obtain mapped heap space. + * + * In the current build model, the user-space module is built first. The + * file user_map.h is generated in the first pass and contains the + * addresses of the memory manager needed in this file: + */ + +#include + +/************************************************************************ + * Pre-processor definition + ************************************************************************/ + +/* This value is obtained from user_map.h */ + +#define KREALLOC(p,s) ((krealloc_t)CONFIG_USER_REALLOC)(p,s) + +/************************************************************************ + * Private Types + ************************************************************************/ + +typedef FAR void *(*krealloc_t)(FAR void*, size_t); + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: krealloc + * + * Description: + * This is a simple redirection to the user-space realloc() function. + * + * Parameters: + * oldmem - The old memory allocated + * size - Size (in bytes) of the new memory region to be re-allocated. + * + * Return Value: + * The address of the re-allocated memory (NULL on failure to re-allocate) + * + * Assumptions: + * 1. realloc() resides in user-space + * 2. The address of the user space realloc() is provided in user_map.h + * 3. The user-space realloc() is callable from kernel-space. + * + ************************************************************************/ + +FAR void *krealloc(FAR void *oldmem, size_t size) +{ + return KREALLOC(oldmem, size); +} + +#endif /* CONFIG_NUTTX_KERNEL */ diff --git a/nuttx/sched/kmm_kzalloc.c b/nuttx/sched/kmm_kzalloc.c new file mode 100644 index 000000000..42bcfcc0f --- /dev/null +++ b/nuttx/sched/kmm_kzalloc.c @@ -0,0 +1,110 @@ +/************************************************************************ + * sched/kmm_kzalloc.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include + +#ifdef CONFIG_NUTTX_KERNEL + +/* This logic is all tentatively and, hopefully, will grow in usability. + * For now, the kernel-mode build uses the memory manager that is + * provided in the user-space build. That is awkward but reasonable for + * the current level of support: At present, only memory protection is + * provided. Kernel-mode code may call into user-mode code, but not + * vice-versa. So hosting the memory manager in user-space allows the + * memory manager to be shared in both kernel- and user-mode spaces. + * + * In the longer run, if an MMU is support that can provide virtualized + * memory, then some SLAB memory manager will be required in kernel-space + * with some kind of brk() system call to obtain mapped heap space. + * + * In the current build model, the user-space module is built first. The + * file user_map.h is generated in the first pass and contains the + * addresses of the memory manager needed in this file: + */ + +#include + +/************************************************************************ + * Pre-processor definition + ************************************************************************/ + +/* This value is obtained from user_map.h */ + +#define KZALLOC(s) ((kzalloc_t)CONFIG_USER_ZALLOC)(s) + +/************************************************************************ + * Private Types + ************************************************************************/ + +typedef FAR void *(*kzalloc_t)(size_t); + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: kzalloc + * + * Description: + * This is a simple redirection to the user-space zalloc() function. + * + * Parameters: + * size - Size (in bytes) of the memory region to be allocated. + * + * Return Value: + * The address of the allocated memory (NULL on failure to allocate) + * + * Assumptions: + * 1. zalloc() resides in user-space + * 2. The address of the user space zalloc() is provided in user_map.h + * 3. The user-space zalloc() is callable from kernel-space. + * + ************************************************************************/ + +FAR void *kzalloc(size_t size) +{ + return KZALLOC(size); +} + +#endif /* CONFIG_NUTTX_KERNEL */ diff --git a/nuttx/sched/kmm_semaphore.c b/nuttx/sched/kmm_semaphore.c new file mode 100644 index 000000000..7fce747b6 --- /dev/null +++ b/nuttx/sched/kmm_semaphore.c @@ -0,0 +1,140 @@ +/************************************************************************ + * sched/kmm_semaphore.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include + +#ifdef CONFIG_NUTTX_KERNEL + +/* This logic is all tentatively and, hopefully, will grow in usability. + * For now, the kernel-mode build uses the memory manager that is + * provided in the user-space build. That is awkward but reasonable for + * the current level of support: At present, only memory protection is + * provided. Kernel-mode code may call into user-mode code, but not + * vice-versa. So hosting the memory manager in user-space allows the + * memory manager to be shared in both kernel- and user-mode spaces. + * + * In the longer run, if an MMU is support that can provide virtualized + * memory, then some SLAB memory manager will be required in kernel-space + * with some kind of brk() system call to obtain mapped heap space. + * + * In the current build model, the user-space module is built first. The + * file user_map.h is generated in the first pass and contains the + * addresses of the memory manager needed in this file: + */ + +#include + +/************************************************************************ + * Pre-processor definition + ************************************************************************/ + +/* These values are obtained from user_map.h */ + +#define KTRYSEMAPHORE() ((kmtrysemaphore_t) CONFIG_USER_MMTRYSEM )() +#define KGIVESEMAPHORE() ((kmgivesemaphore_t)CONFIG_USER_MMGIVESEM)() + +/************************************************************************ + * Private Types + ************************************************************************/ + +typedef int (*kmtrysemaphore_t)(void); +typedef void (*kmgivesemaphore_t)(void); + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: kmm_trysemaphore + * + * Description: + * This is a simple redirection to the user-space mm_trysemaphore() + * function. + * + * Parameters: + * None + * + * Return Value: + * OK on success; a negated errno on failure + * + * Assumptions: + * 1. mm_trysemaphore() resides in user-space + * 2. The address of the user space mm_trysemaphore() is provided in + * user_map.h + * 3. The user-space mm_semaphore() is callable from kernel-space. + * + ************************************************************************/ + +int kmm_trysemaphore(void) +{ + return KTRYSEMAPHORE(); +} + +/************************************************************************ + * Name: kmm_givesemaphore + * + * Description: + * This is a simple redirection to the user-space mm_givesemaphore() + * function. + * + * Parameters: + * None + * + * Return Value: + * OK on success; a negated errno on failure + * + * Assumptions: + * 1. mm_givesemaphore() resides in user-space + * 2. The address of the user space mm_givesemaphore() is provided in + * user_map.h + * 3. The user-space mm_semaphore() is callable from kernel-space. + * + ************************************************************************/ + +void kmm_givesemaphore(void) +{ + KGIVESEMAPHORE(); +} + +#endif /* CONFIG_NUTTX_KERNEL */ diff --git a/nuttx/sched/mq_close.c b/nuttx/sched/mq_close.c new file mode 100644 index 000000000..57780a8e6 --- /dev/null +++ b/nuttx/sched/mq_close.c @@ -0,0 +1,187 @@ +/**************************************************************************** + * sched/mq_close.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include + +#include "os_internal.h" +#include "mq_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mq_desfree + * + * Description: + * Deallocate a message queue descriptor but returning it to the free list + * + * Inputs: + * mqdes - message queue descriptor to free + * + ****************************************************************************/ + +#define mq_desfree(mqdes) sq_addlast((FAR sq_entry_t*)mqdes, &g_desfree) + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mq_close + * + * Description: + * This function is used to indicate that the calling task is finished + * with the specified message queued mqdes. The mq_close() deallocates + * any system resources allocated by the system for use by this task for + * its message queue. + * + * If the calling task has attached a notification to the message queue + * via this mqdes, this attachment will be removed and the message queue + * is available for another process to attach a notification. + * + * Parameters: + * mqdes - Message queue descriptor. + * + * Return Value: + * 0 (OK) if the message queue is closed successfully, + * otherwise, -1 (ERROR). + * + * Assumptions: + * - The behavior of a task that is blocked on either a mq_send() or + * mq_receive() is undefined when mq_close() is called. + * - The results of using this message queue descriptor after a successful + * return from mq_close() is undefined. + * + ****************************************************************************/ + +int mq_close(mqd_t mqdes) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + FAR msgq_t *msgq; + irqstate_t saved_state; + int ret = ERROR; + + /* Verify the inputs */ + + if (mqdes) + { + sched_lock(); + + /* Remove the message descriptor from the current task's + * list of message descriptors. + */ + + sq_rem((FAR sq_entry_t*)mqdes, &rtcb->msgdesq); + + /* Find the message queue associated with the message descriptor */ + + msgq = mqdes->msgq; + + /* Check if the calling task has a notification attached to + * the message queue via this mqdes. + */ + +#ifndef CONFIG_DISABLE_SIGNALS + if (msgq->ntmqdes == mqdes) + { + msgq->ntpid = INVALID_PROCESS_ID; + msgq->ntsigno = 0; + msgq->ntvalue.sival_int = 0; + msgq->ntmqdes = NULL; + } +#endif + + /* Decrement the connection count on the message queue. */ + + if (msgq->nconnect) + { + msgq->nconnect--; + } + + /* If it is no longer connected to any message descriptor and if the + * message queue has already been unlinked, then we can discard the + * message queue. + */ + + if (!msgq->nconnect && msgq->unlinked) + { + /* Remove the message queue from the list of all + * message queues + */ + + saved_state = irqsave(); + (void)sq_rem((FAR sq_entry_t*)msgq, &g_msgqueues); + irqrestore(saved_state); + + /* Then deallocate it (and any messages left in it) */ + + mq_msgqfree(msgq); + } + + /* Deallocate the message descriptor */ + + mq_desfree(mqdes); + + sched_unlock(); + ret = OK; + } + + return ret; +} + diff --git a/nuttx/sched/mq_descreate.c b/nuttx/sched/mq_descreate.c new file mode 100644 index 000000000..14937888c --- /dev/null +++ b/nuttx/sched/mq_descreate.c @@ -0,0 +1,159 @@ +/**************************************************************************** + * sched/mq_descreate.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "os_internal.h" +#include "sig_internal.h" + +#include "mq_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mq_desalloc + * + * Description: + * Allocate a message queue descriptor. + * + * Inputs: + * None + * + * Return Value: + * Reference to the allocated mq descriptor. + * + ****************************************************************************/ + +static mqd_t mq_desalloc(void) +{ + mqd_t mqdes; + + /* Try to get the message descriptorfrom the free list */ + + mqdes = (mqd_t)sq_remfirst(&g_desfree); + + /* Check if we got one. */ + + if (!mqdes) + { + /* Add another block of message descriptors to the list */ + + mq_desblockalloc(); + + /* And try again */ + + mqdes = (mqd_t)sq_remfirst(&g_desfree); + } + + return mqdes; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mq_descreate + * + * Description: + * Create a message queue descriptor for the specified TCB + * + * Inputs: + * TCB - task that needs the descriptor. + * msgq - Named message queue containing the message + * oflags - access rights for the descriptor + * + * Return Value: + * On success, the message queue descriptor is returned. NULL is returned + * on a failure to allocate. + * + ****************************************************************************/ + +mqd_t mq_descreate(FAR _TCB* mtcb, FAR msgq_t* msgq, int oflags) +{ + mqd_t mqdes; + + /* Create a message queue descriptor for the TCB */ + + mqdes = mq_desalloc(); + if (mqdes) + { + /* Initialize the MQ descriptor */ + + memset(mqdes, 0, sizeof(struct mq_des)); + mqdes->msgq = msgq; + mqdes->oflags = oflags; + + /* And add it to the specified tasks's TCB */ + + sq_addlast((FAR sq_entry_t*)mqdes, &mtcb->msgdesq); + } + + return mqdes; +} diff --git a/nuttx/sched/mq_findnamed.c b/nuttx/sched/mq_findnamed.c new file mode 100644 index 000000000..d23b81c5e --- /dev/null +++ b/nuttx/sched/mq_findnamed.c @@ -0,0 +1,105 @@ +/************************************************************************ + * sched/mq_findnamed.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include + +#include "mq_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: mq_findnamed + * + * Description: + * This function finds the named message queue with the specified name + * in the list of message queues. + * + * Inputs: + * mq_name - the name of the message queue to find + * + * Return Value: + * A reference to the matching named message queue structure (or NULL + * if none was found). + * + ************************************************************************/ + +FAR msgq_t *mq_findnamed(const char *mq_name) +{ + FAR msgq_t *msgq; + + /* Search the list of named message queues */ + + for (msgq = (FAR msgq_t*)g_msgqueues.head; (msgq); msgq = msgq->flink) + { + /* Break out of the lloop with a non-NULL msgq if the + * name matches. + */ + + if (!strcmp(mq_name, msgq->name)) + { + break; + } + } + + return msgq; +} diff --git a/nuttx/sched/mq_initialize.c b/nuttx/sched/mq_initialize.c new file mode 100644 index 000000000..5b03a1120 --- /dev/null +++ b/nuttx/sched/mq_initialize.c @@ -0,0 +1,243 @@ +/************************************************************************ + * sched/mq_initialize.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include + +#include "mq_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/* This is a container for a list of message queue descriptors. */ + +struct mq_des_block_s +{ + sq_entry_t queue; + struct mq_des mqdes[NUM_MSG_DESCRIPTORS]; +}; + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/* This is a list of all opened message queues */ + +sq_queue_t g_msgqueues; + +/* The g_msgfree is a list of messages that are available for general + * use. The number of messages in this list is a system configuration + * item. + */ + +sq_queue_t g_msgfree; + +/* The g_msgfreeInt is a list of messages that are reserved for use by + * interrupt handlers. + */ + +sq_queue_t g_msgfreeirq; + +/* The g_desfree data structure is a list of message descriptors available + * to the operating system for general use. The number of messages in the + * pool is a constant. + */ + +sq_queue_t g_desfree; + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/* g_msgalloc is a pointer to the start of the allocated block of + * messages. + */ + +static mqmsg_t *g_msgalloc; + +/* g_msgfreeirqalloc is a pointer to the start of the allocated block of + * messages. + */ + +static mqmsg_t *g_msgfreeirqalloc; + +/* g_desalloc is a list of allocated block of message queue descriptors. */ + +static sq_queue_t g_desalloc; + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Name: mq_msgblockalloc + * + * Description: + * Allocate a block of messages and place them on the free list. + * + * Inputs Parameters: + * queue + * + ************************************************************************/ + +static mqmsg_t *mq_msgblockalloc(sq_queue_t *queue, uint16_t nmsgs, + uint8_t alloc_type) +{ + mqmsg_t *mqmsgblock; + + /* The g_msgfree must be loaded at initialization time to hold the + * configured number of messages. + */ + + mqmsgblock = (mqmsg_t*)kmalloc(sizeof(mqmsg_t) * nmsgs); + if (mqmsgblock) + { + mqmsg_t *mqmsg = mqmsgblock; + int i; + + for (i = 0; i < nmsgs; i++) + { + mqmsg->type = alloc_type; + sq_addlast((FAR sq_entry_t*)mqmsg++, queue); + } + } + + return mqmsgblock; +} + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: mq_initialize + * + * Description: + * This function initializes the messasge system. This function must + * be called early in the initialization sequence before any of the + * other message interfaces execute. + * + * Inputs: + * None + * + * Return Value: + * None + * + ************************************************************************/ + +void mq_initialize(void) +{ + /* Initialize the list of message queues */ + + sq_init(&g_msgqueues); + + /* Initialize the message free lists */ + + sq_init(&g_msgfree); + sq_init(&g_msgfreeirq); + sq_init(&g_desalloc); + + /* Allocate a block of messages for general use */ + + g_msgalloc = + mq_msgblockalloc(&g_msgfree, CONFIG_PREALLOC_MQ_MSGS, + MQ_ALLOC_FIXED); + + /* Allocate a block of messages for use exclusively by + * interrupt handlers + */ + + g_msgfreeirqalloc = + mq_msgblockalloc(&g_msgfreeirq, NUM_INTERRUPT_MSGS, + MQ_ALLOC_IRQ); + + /* Allocate a block of message queue descriptors */ + + mq_desblockalloc(); +} + +/************************************************************************ + * Name: mq_desblockalloc + * + * Description: + * Allocate a block of message descriptors and place them on the free + * list. + * + * Inputs: + * None + * + * Return Value: + * None + * + ************************************************************************/ + +void mq_desblockalloc(void) +{ + struct mq_des_block_s *mqdesblock; + + /* Allocate a block of message descriptors */ + + mqdesblock = (struct mq_des_block_s *)kmalloc(sizeof(struct mq_des_block_s)); + if (mqdesblock) + { + int i; + + /* Add the block to the list of allocated blocks (in case + * we ever need to reclaim the memory. + */ + + sq_addlast((FAR sq_entry_t*)&mqdesblock->queue, &g_desalloc); + + /* Then add each message queue descriptor to the free list */ + + for (i = 0; i < NUM_MSG_DESCRIPTORS; i++) + { + sq_addlast((FAR sq_entry_t*)&mqdesblock->mqdes[i], &g_desfree); + } + } +} + diff --git a/nuttx/sched/mq_internal.h b/nuttx/sched/mq_internal.h new file mode 100644 index 000000000..6135bfaef --- /dev/null +++ b/nuttx/sched/mq_internal.h @@ -0,0 +1,183 @@ +/**************************************************************************** + * sched/mq_internal.h + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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. + * + ****************************************************************************/ + +#ifndef __SCHED_MQ_INTERNAL_H +#define __SCHED_MQ_INTERNAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#if CONFIG_MQ_MAXMSGSIZE > 0 + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define MQ_MAX_BYTES CONFIG_MQ_MAXMSGSIZE +#define MQ_MAX_MSGS 16 +#define MQ_PRIO_MAX _POSIX_MQ_PRIO_MAX + +/* This defines the number of messages descriptors to allocate at each + * "gulp." + */ + +#define NUM_MSG_DESCRIPTORS 24 + +/* This defines the number of messages to set aside for exclusive use by + * interrupt handlers + */ + +#define NUM_INTERRUPT_MSGS 8 + +/**************************************************************************** + * Global Type Declarations + ****************************************************************************/ + +enum mqalloc_e +{ + MQ_ALLOC_FIXED = 0, /* pre-allocated; never freed */ + MQ_ALLOC_DYN, /* dynamically allocated; free when unused */ + MQ_ALLOC_IRQ /* Preallocated, reserved for interrupt handling */ +}; + +typedef enum mqalloc_e mqalloc_t; + +/* This structure describes one buffered POSIX message. */ + +struct mqmsg +{ + FAR struct mqmsg *next; /* Forward link to next message */ + uint8_t type; /* (Used to manage allocations) */ + uint8_t priority; /* priority of message */ +#if MQ_MAX_BYTES < 256 + uint8_t msglen; /* Message data length */ +#else + uint16_t msglen; /* Message data length */ +#endif + uint8_t mail[MQ_MAX_BYTES]; /* Message data */ +}; + +typedef struct mqmsg mqmsg_t; + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/* This is a list of all opened message queues */ + +extern sq_queue_t g_msgqueues; + +/* The g_msgfree is a list of messages that are available for general use. + * The number of messages in this list is a system configuration item. + */ + +extern sq_queue_t g_msgfree; + +/* The g_msgfreeInt is a list of messages that are reserved for use by + * interrupt handlers. + */ + +extern sq_queue_t g_msgfreeirq; + +/* The g_desfree data structure is a list of message descriptors available + * to the operating system for general use. The number of messages in the + * pool is a constant. + */ + +extern sq_queue_t g_desfree; + +/**************************************************************************** + * Global Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/* Functions defined in mq_initialize.c ************************************/ + +EXTERN void weak_function mq_initialize(void); +EXTERN void mq_desblockalloc(void); + +EXTERN mqd_t mq_descreate(FAR _TCB* mtcb, FAR msgq_t* msgq, int oflags); +EXTERN FAR msgq_t *mq_findnamed(const char *mq_name); +EXTERN void mq_msgfree(FAR mqmsg_t *mqmsg); +EXTERN void mq_msgqfree(FAR msgq_t *msgq); + +/* mq_waitirq.c ************************************************************/ + +EXTERN void mq_waitirq(FAR _TCB *wtcb, int errcode); + +/* mq_rcvinternal.c ********************************************************/ + +EXTERN int mq_verifyreceive(mqd_t mqdes, void *msg, size_t msglen); +EXTERN FAR mqmsg_t *mq_waitreceive(mqd_t mqdes); +EXTERN ssize_t mq_doreceive(mqd_t mqdes, mqmsg_t *mqmsg, void *ubuffer, + int *prio); + +/* mq_sndinternal.c ********************************************************/ + +EXTERN int mq_verifysend(mqd_t mqdes, const void *msg, size_t msglen, + int prio); +EXTERN FAR mqmsg_t *mq_msgalloc(void); +EXTERN int mq_waitsend(mqd_t mqdes); +EXTERN int mq_dosend(mqd_t mqdes, FAR mqmsg_t *mqmsg, const void *msg, + size_t msglen, int prio); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* CONFIG_MQ_MAXMSGSIZE > 0 */ +#endif /* __SCHED_MQ_INTERNAL_H */ + diff --git a/nuttx/sched/mq_msgfree.c b/nuttx/sched/mq_msgfree.c new file mode 100644 index 000000000..91322fbf3 --- /dev/null +++ b/nuttx/sched/mq_msgfree.c @@ -0,0 +1,134 @@ +/************************************************************************ + * sched/mq_msgfree.c + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include "os_internal.h" +#include "mq_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: mq_msgfree + * + * Description: + * The mq_msgfree function will return a message to the free pool of + * messages if it was a pre-allocated message. If the message was + * allocated dynamically it will be deallocated. + * + * Inputs: + * mqmsg - message to free + * + * Return Value: + * None + * + ************************************************************************/ + +void mq_msgfree(FAR mqmsg_t *mqmsg) +{ + irqstate_t saved_state; + + /* If this is a generally available pre-allocated message, + * then just put it back in the free list. + */ + + if (mqmsg->type == MQ_ALLOC_FIXED) + { + /* Make sure we avoid concurrent access to the free + * list from interrupt handlers. + */ + + saved_state = irqsave(); + sq_addlast((FAR sq_entry_t*)mqmsg, &g_msgfree); + irqrestore(saved_state); + } + + /* If this is a message pre-allocated for interrupts, + * then put it back in the correct free list. + */ + + else if (mqmsg->type == MQ_ALLOC_IRQ) + { + /* Make sure we avoid concurrent access to the free + * list from interrupt handlers. + */ + + saved_state = irqsave(); + sq_addlast((FAR sq_entry_t*)mqmsg, &g_msgfreeirq); + irqrestore(saved_state); + } + + /* Otherwise, deallocate it. Note: interrupt handlers + * will never deallocate messages because they will not + * received them. + */ + + else if (mqmsg->type == MQ_ALLOC_DYN) + { + sched_free(mqmsg); + } + else + { + PANIC(OSERR_BADMSGTYPE); + } +} diff --git a/nuttx/sched/mq_msgqfree.c b/nuttx/sched/mq_msgqfree.c new file mode 100644 index 000000000..d7d87db3d --- /dev/null +++ b/nuttx/sched/mq_msgqfree.c @@ -0,0 +1,108 @@ +/************************************************************************ + * sched/mq_msgqfree.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include "mq_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: mq_msgqfree + * + * Description: + * This function deallocates an initialized message queue + * structure. First, it deallocates all of the queued + * messages in the message Q. It is assumed that this + * message is fully unlinked and closed so that not thread + * will attempt access it while it is being deleted. + * + * Inputs: + * msgq - Named essage queue to be freed + * + * Return Value: + * None + * + ************************************************************************/ + +void mq_msgqfree(FAR msgq_t *msgq) +{ + FAR mqmsg_t *curr; + FAR mqmsg_t *next; + + /* Deallocate any stranded messages in the message queue. */ + + curr = (FAR mqmsg_t*)msgq->msglist.head; + while (curr) + { + /* Deallocate the message structure. */ + + next = curr->next; + mq_msgfree(curr); + curr = next; + } + + /* Then deallocate the message queue itself */ + + sched_free(msgq); +} diff --git a/nuttx/sched/mq_notify.c b/nuttx/sched/mq_notify.c new file mode 100644 index 000000000..589bee312 --- /dev/null +++ b/nuttx/sched/mq_notify.c @@ -0,0 +1,211 @@ +/************************************************************************ + * sched/mq_notify.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include + +#include "os_internal.h" +#include "mq_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: mq_notify + * + * Description: + * If "notification" is not NULL, this function connects the task with + * the message queue such that the specified signal will be sent to the + * task whenever the message changes from empty to non-empty. Only one + * notification can be attached to a message queue. + * + * If "notification" is NULL, the attached notification is detached (if + * it was held by the calling task) and the queue is available to attach + * another notification. + * + * When the notification is sent to the registered process, its + * registration will be removed. The message queue will then be + * available for registration. + * + * Parameters: + * mqdes - Message queue descriptor + * notification - Real-time signal structure containing: + * sigev_notify - Should be SIGEV_SIGNAL (but actually ignored) + * sigev_signo - The signo to use for the notification + * sigev_value - Value associated with the signal + * + * Return Value: + * On success mq_notify() returns 0; on error, -1 is returned, with + * errno set to indicate the error. + * + * EBADF The descriptor specified in mqdes is invalid. + * EBUSY Another process has already registered to receive notification + * for this message queue. + * EINVAL sevp->sigev_notify is not one of the permitted values; or + * sevp->sigev_notify is SIGEV_SIGNAL and sevp->sigev_signo is not a + * valid signal number. + * ENOMEM + * Insufficient memory. + * + * Assumptions: + * + * POSIX Compatibility: + * int mq_notify(mqd_t mqdes, const struct sigevent *notification); + * + * The notification will be sent to the registered task even if another + * task is waiting for the message queue to become non-empty. This is + * inconsistent with the POSIX specification which says, "If a process + * has registered for notification of message a arrival at a message + * queue and some process is blocked in mq_receive() waiting to receive + * a message when a message arrives at the queue, the arriving message + * message shall satisfy mq_receive()... The resulting behavior is as if + * the message queue remains empty, and no notification shall be sent." + * + ************************************************************************/ + +int mq_notify(mqd_t mqdes, const struct sigevent *notification) +{ + _TCB *rtcb; + msgq_t *msgq; + int errval; + + /* Was a valid message queue descriptor provided? */ + + if (!mqdes) + { + /* No.. return EBADF */ + + errval = EBADF; + goto errout; + } + + /* Get a pointer to the message queue */ + + sched_lock(); + msgq = mqdes->msgq; + + /* Get the current process ID */ + + rtcb = (_TCB*)g_readytorun.head; + + /* Is there already a notification attached */ + + if (!msgq->ntmqdes) + { + /* No... Have we been asked to establish one? */ + + if (notification) + { + /* Yes... Was a valid signal number supplied? */ + + if (!GOOD_SIGNO(notification->sigev_signo)) + { + /* No... Return EINVAL */ + + errval = EINVAL; + goto errout; + } + + /* Yes... Assign it to the current task. */ + + msgq->ntvalue.sival_ptr = notification->sigev_value.sival_ptr; + msgq->ntsigno = notification->sigev_signo; + msgq->ntpid = rtcb->pid; + msgq->ntmqdes = mqdes; + } + } + + /* Yes... a notification is attached. Does this task own it? + * Is it trying to remove it? + */ + + else if ((msgq->ntpid != rtcb->pid) || (notification)) + { + /* This thread does not own the notification OR it is + * not trying to remove it. Return EBUSY. + */ + + errval = EBUSY; + goto errout; + } + else + { + /* Yes, the notification belongs to this thread. Allow the + * thread to detach the notification. + */ + + msgq->ntpid = INVALID_PROCESS_ID; + msgq->ntsigno = 0; + msgq->ntvalue.sival_ptr = NULL; + msgq->ntmqdes = NULL; + } + + sched_unlock(); + return OK; + +errout: + set_errno(errval); + sched_unlock(); + return ERROR; +} diff --git a/nuttx/sched/mq_open.c b/nuttx/sched/mq_open.c new file mode 100644 index 000000000..5e1b9b137 --- /dev/null +++ b/nuttx/sched/mq_open.c @@ -0,0 +1,236 @@ +/**************************************************************************** + * sched/mq_open.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "os_internal.h" +#include "mq_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mq_open + * + * Description: + * This function establish a connection between a named message queue and + * the calling task. After a successful call of mq_open(), the task can + * reference the message queue using the address returned by the call. The + * message queue remains usable until it is closed by a successful call to + * mq_close(). + * + * Parameters: + * mq_name - Name of the queue to open + * oflags - open flags + * Optional parameters. When the O_CREAT flag is specified, two optional + * parameters are expected: + * + * 1. mode_t mode (ignored), and + * 2. struct mq_attr *attr. The mq_maxmsg attribute + * is used at the time that the message queue is + * created to determine the maximum number of + * messages that may be placed in the message queue. + * + * Return Value: + * A message queue descriptor or -1 (ERROR) + * + * Assumptions: + * + ****************************************************************************/ + +mqd_t mq_open(const char *mq_name, int oflags, ...) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + FAR msgq_t *msgq; + mqd_t mqdes = NULL; + va_list arg; /* Points to each un-named argument */ + mode_t mode; /* MQ creation mode parameter (ignored) */ + struct mq_attr *attr; /* MQ creation attributes */ + int namelen; /* Length of MQ name */ + + /* Make sure that a non-NULL name is supplied */ + + if (mq_name) + { + sched_lock(); + namelen = strlen(mq_name); + if (namelen > 0) + { + /* See if the message queue already exists */ + + msgq = mq_findnamed(mq_name); + if (msgq) + { + /* It does. Check if the caller wanted to create a new + * message queue with this name (i.e., O_CREAT|O_EXCL) + */ + + if ((oflags & O_CREAT) == 0 || (oflags & O_EXCL) == 0) + { + /* Create a message queue descriptor for the TCB */ + + mqdes = mq_descreate(rtcb, msgq, oflags); + if (mqdes) + { + /* Allow a new connection to the message queue */ + + msgq->nconnect++; + } + } + } + + /* It doesn't exist. Should we create one? */ + + else if ((oflags & O_CREAT) != 0) + { + /* Allocate memory for the new message queue. The size to + * allocate is the size of the msgq_t header plus the size + * of the message queue name+1. + */ + + msgq = (FAR msgq_t*)kzalloc(SIZEOF_MQ_HEADER + namelen + 1); + if (msgq) + { + /* Create a message queue descriptor for the TCB */ + + mqdes = mq_descreate(rtcb, msgq, oflags); + if (mqdes) + { + /* Set up to get the optional arguments needed to create + * a message queue. + */ + + va_start(arg, oflags); + mode = va_arg(arg, mode_t); + attr = va_arg(arg, struct mq_attr*); + + /* Initialize the new named message queue */ + + sq_init(&msgq->msglist); + if (attr) + { + msgq->maxmsgs = (int16_t)attr->mq_maxmsg; + if (attr->mq_msgsize <= MQ_MAX_BYTES) + { + msgq->maxmsgsize = (int16_t)attr->mq_msgsize; + } + else + { + msgq->maxmsgsize = MQ_MAX_BYTES; + } + } + else + { + msgq->maxmsgs = MQ_MAX_MSGS; + msgq->maxmsgsize = MQ_MAX_BYTES; + } + + msgq->nconnect = 1; +#ifndef CONFIG_DISABLE_SIGNALS + msgq->ntpid = INVALID_PROCESS_ID; +#endif + strcpy(msgq->name, mq_name); + + /* Add the new message queue to the list of + * message queues + */ + + sq_addlast((FAR sq_entry_t*)msgq, &g_msgqueues); + + /* Clean-up variable argument stuff */ + + va_end(arg); + } + else + { + /* Deallocate the msgq structure. Since it is + * uninitialized, mq_deallocate() is not used. + */ + + sched_free(msgq); + } + } + } + } + + sched_unlock(); + } + + if (mqdes == NULL) + { + return (mqd_t)ERROR; + } + else + { + return mqdes; + } +} diff --git a/nuttx/sched/mq_rcvinternal.c b/nuttx/sched/mq_rcvinternal.c new file mode 100644 index 000000000..e80685e87 --- /dev/null +++ b/nuttx/sched/mq_rcvinternal.c @@ -0,0 +1,312 @@ +/**************************************************************************** + * sched/mq_rcvinternal.c + * + * Copyright (C) 2007, 2008, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "os_internal.h" +#include "mq_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mq_verifyreceive + * + * Description: + * This is internal, common logic shared by both mq_receive and + * mq_timedreceive. This function verifies the input parameters that are + * common to both functions. + * + * Parameters: + * mqdes - Message Queue Descriptor + * msg - Buffer to receive the message + * msglen - Size of the buffer in bytes + * + * Return Value: + * One success, 0 (OK) is returned. On failure, -1 (ERROR) is returned and + * the errno is set appropriately: + * + * EPERM Message queue opened not opened for reading. + * EMSGSIZE 'msglen' was less than the maxmsgsize attribute of the message + * queue. + * EINVAL Invalid 'msg' or 'mqdes' + * + * Assumptions: + * + ****************************************************************************/ + +int mq_verifyreceive(mqd_t mqdes, void *msg, size_t msglen) +{ + /* Verify the input parameters */ + + if (!msg || !mqdes) + { + set_errno(EINVAL); + return ERROR; + } + + if ((mqdes->oflags & O_RDOK) == 0) + { + set_errno(EPERM); + return ERROR; + } + + if (msglen < (size_t)mqdes->msgq->maxmsgsize) + { + set_errno(EMSGSIZE); + return ERROR; + } + + return OK; +} + +/**************************************************************************** + * Name: mq_waitreceive + * + * Description: + * This is internal, common logic shared by both mq_receive and + * mq_timedreceive. This function waits for a message to be received on + * the specified message queue, removes the message from the queue, and + * returns it. + * + * Parameters: + * mqdes - Message queue descriptor + * + * Return Value: + * On success, a reference to the received message. If the wait was + * interrupted by a signal or a timeout, then the errno will be set + * appropriately and NULL will be returned. + * + * Assumptions: + * - The caller has provided all validity checking of the input parameters + * using mq_verifyreceive. + * - Interrupts should be disabled throughout this call. This is necessary + * because messages can be sent from interrupt level processing. + * - For mq_timedreceive, setting of the timer and this wait must be atomic. + * + ****************************************************************************/ + +FAR mqmsg_t *mq_waitreceive(mqd_t mqdes) +{ + FAR _TCB *rtcb; + FAR msgq_t *msgq; + FAR mqmsg_t *rcvmsg; + + /* Get a pointer to the message queue */ + + msgq = mqdes->msgq; + + /* Get the message from the head of the queue */ + + while ((rcvmsg = (FAR mqmsg_t*)sq_remfirst(&msgq->msglist)) == NULL) + { + /* The queue is empty! Should we block until there the above condition + * has been satisfied? + */ + + if ((mqdes->oflags & O_NONBLOCK) == 0) + { + /* Yes.. Block and try again */ + + rtcb = (FAR _TCB*)g_readytorun.head; + rtcb->msgwaitq = msgq; + msgq->nwaitnotempty++; + + set_errno(OK); + up_block_task(rtcb, TSTATE_WAIT_MQNOTEMPTY); + + /* When we resume at this point, either (1) the message queue + * is no longer empty, or (2) the wait has been interrupted by + * a signal. We can detect the latter case be examining the + * errno value (should be either EINTR or ETIMEDOUT). + */ + + if (get_errno() != OK) + { + break; + } + } + else + { + /* The queue was empty, and the O_NONBLOCK flag was set for the + * message queue description referred to by 'mqdes'. + */ + + set_errno(EAGAIN); + break; + } + } + + /* If we got message, then decrement the number of messages in + * the queue while we are still in the critical section + */ + + if (rcvmsg) + { + msgq->nmsgs--; + } + + return rcvmsg; +} + +/**************************************************************************** + * Name: mq_doreceive + * + * Description: + * This is internal, common logic shared by both mq_receive and + * mq_timedreceive. This function accepts the message obtained by + * mq_waitmsg, provides the message content to the user, notifies any + * threads that were waiting for the message queue to become non-full, + * and disposes of the message structure + * + * Parameters: + * mqdes - Message queue descriptor + * mqmsg - The message obtained by mq_waitmsg() + * ubuffer - The address of the user provided buffer to receive the message + * prio - The user-provided location to return the message priority. + * + * Return Value: + * Returns the length of the received message. This function does not fail. + * + * Assumptions: + * - The caller has provided all validity checking of the input parameters + * using mq_verifyreceive. + * - The user buffer, ubuffer, is known to be large enough to accept the + * largest message that an be sent on this message queue + * - Pre-emption should be disabled throughout this call. + * + ****************************************************************************/ + +ssize_t mq_doreceive(mqd_t mqdes, mqmsg_t *mqmsg, void *ubuffer, int *prio) +{ + FAR _TCB *btcb; + irqstate_t saved_state; + FAR msgq_t *msgq; + ssize_t rcvmsglen; + + /* Get the length of the message (also the return value) */ + + rcvmsglen = mqmsg->msglen; + + /* Copy the message into the caller's buffer */ + + memcpy(ubuffer, (const void*)mqmsg->mail, rcvmsglen); + + /* Copy the message priority as well (if a buffer is provided) */ + + if (prio) + { + *prio = mqmsg->priority; + } + + /* We are done with the message. Deallocate it now. */ + + mq_msgfree(mqmsg); + + /* Check if any tasks are waiting for the MQ not full event. */ + + msgq = mqdes->msgq; + if (msgq->nwaitnotfull > 0) + { + /* Find the highest priority task that is waiting for + * this queue to be not-full in g_waitingformqnotfull list. + * This must be performed in a critical section because + * messages can be sent from interrupt handlers. + */ + + saved_state = irqsave(); + for (btcb = (FAR _TCB*)g_waitingformqnotfull.head; + btcb && btcb->msgwaitq != msgq; + btcb = btcb->flink); + + /* If one was found, unblock it. NOTE: There is a race + * condition here: the queue might be full again by the + * time the task is unblocked + */ + + if (!btcb) + { + PANIC(OSERR_MQNOTFULLCOUNT); + } + else + { + btcb->msgwaitq = NULL; + msgq->nwaitnotfull--; + up_unblock_task(btcb); + } + + irqrestore(saved_state); + } + + /* Return the length of the message transferred to the user buffer */ + + return rcvmsglen; +} diff --git a/nuttx/sched/mq_receive.c b/nuttx/sched/mq_receive.c new file mode 100644 index 000000000..760433446 --- /dev/null +++ b/nuttx/sched/mq_receive.c @@ -0,0 +1,166 @@ +/************************************************************************ + * sched/mq_receive.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include +#include + +#include "mq_internal.h" + +/************************************************************************ + * Pre-processor Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: mq_receive + * + * Description: + * This function receives the oldest of the highest priority messages + * from the message queue specified by "mqdes." If the size of the + * buffer in bytes (msglen) is less than the "mq_msgsize" attribute of + * the message queue, mq_receive will return an error. Otherwise, the + * selected message is removed from the queue and copied to "msg." + * + * If the message queue is empty and O_NONBLOCK was not set, + * mq_receive() will block until a message is added to the message + * queue. If more than one task is waiting to receive a message, only + * the task with the highest priority that has waited the longest will + * be unblocked. + * + * If the queue is empty and O_NONBLOCK is set, ERROR will be returned. + * + * Parameters: + * mqdes - Message Queue Descriptor + * msg - Buffer to receive the message + * msglen - Size of the buffer in bytes + * prio - If not NULL, the location to store message priority. + * + * Return Value: + * One success, the length of the selected message in bytes is returned. + * On failure, -1 (ERROR) is returned and the errno is set appropriately: + * + * EAGAIN The queue was empty, and the O_NONBLOCK flag was set + * for the message queue description referred to by 'mqdes'. + * EPERM Message queue opened not opened for reading. + * EMSGSIZE 'msglen' was less than the maxmsgsize attribute of the + * message queue. + * EINTR The call was interrupted by a signal handler. + * EINVAL Invalid 'msg' or 'mqdes' + * + * Assumptions: + * + ************************************************************************/ + +ssize_t mq_receive(mqd_t mqdes, void *msg, size_t msglen, int *prio) +{ + FAR mqmsg_t *mqmsg; + irqstate_t saved_state; + ssize_t ret = ERROR; + + DEBUGASSERT(up_interrupt_context() == false); + + /* Verify the input parameters and, in case of an error, set + * errno appropriately. + */ + + if (mq_verifyreceive(mqdes, msg, msglen) != OK) + { + return ERROR; + } + + /* Get the next mesage from the message queue. We will disable + * pre-emption until we have completed the message received. This + * is not too bad because if the receipt takes a long time, it will + * be because we are blocked waiting for a message and pre-emption + * will be re-enabled while we are blocked + */ + + sched_lock(); + + /* Furthermore, mq_waitreceive() expects to have interrupts disabled + * because messages can be sent from interrupt level. + */ + + saved_state = irqsave(); + + /* Get the message from the message queue */ + + mqmsg = mq_waitreceive(mqdes); + irqrestore(saved_state); + + /* Check if we got a message from the message queue. We might + * not have a message if: + * + * - The message queue is empty and O_NONBLOCK is set in the mqdes + * - The wait was interrupted by a signal + */ + + if (mqmsg) + { + ret = mq_doreceive(mqdes, mqmsg, msg, prio); + } + + sched_unlock(); + return ret; +} diff --git a/nuttx/sched/mq_send.c b/nuttx/sched/mq_send.c new file mode 100644 index 000000000..40628e924 --- /dev/null +++ b/nuttx/sched/mq_send.c @@ -0,0 +1,184 @@ +/**************************************************************************** + * sched/mq_send.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include + +#include + +#include "os_internal.h" +#include "mq_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mq_send + * + * Description: + * This function adds the specificied message (msg) to the message queue + * (mqdes). The "msglen" parameter specifies the length of the message + * in bytes pointed to by "msg." This length must not exceed the maximum + * message length from the mq_getattr(). + * + * If the message queue is not full, mq_send() place the message in the + * message queue at the position indicated by the "prio" argrument. + * Messages with higher priority will be inserted before lower priority + * messages. The value of "prio" must not exceed MQ_PRIO_MAX. + * + * If the specified message queue is full and O_NONBLOCK is not set in the + * message queue, then mq_send() will block until space becomes available + * to the queue the message. + * + * If the message queue is full and O_NONBLOCK is set, the message is not + * queued and ERROR is returned. + * + * Parameters: + * mqdes - Message queue descriptor + * msg - Message to send + * msglen - The length of the message in bytes + * prio - The priority of the message + * + * Return Value: + * On success, mq_send() returns 0 (OK); on error, -1 (ERROR) + * is returned, with errno set to indicate the error: + * + * EAGAIN The queue was empty, and the O_NONBLOCK flag was set for the + * message queue description referred to by mqdes. + * EINVAL Either msg or mqdes is NULL or the value of prio is invalid. + * EPERM Message queue opened not opened for writing. + * EMSGSIZE 'msglen' was greater than the maxmsgsize attribute of the + * message queue. + * EINTR The call was interrupted by a signal handler. + * + * Assumptions/restrictions: + * + ****************************************************************************/ + +int mq_send(mqd_t mqdes, const void *msg, size_t msglen, int prio) +{ + FAR msgq_t *msgq; + FAR mqmsg_t *mqmsg = NULL; + irqstate_t saved_state; + int ret = ERROR; + + /* Verify the input parameters -- setting errno appropriately + * on any failures to verify. + */ + + if (mq_verifysend(mqdes, msg, msglen, prio) != OK) + { + return ERROR; + } + + /* Get a pointer to the message queue */ + + sched_lock(); + msgq = mqdes->msgq; + + /* Allocate a message structure: + * - Immediately if we are called from an interrupt handler. + * - Immediately if the message queue is not full, or + * - After successfully waiting for the message queue to become + * non-FULL. This would fail with EAGAIN, EINTR, or ETIMEOUT. + */ + + saved_state = irqsave(); + if (up_interrupt_context() || /* In an interrupt handler */ + msgq->nmsgs < msgq->maxmsgs || /* OR Message queue not full */ + mq_waitsend(mqdes) == OK) /* OR Successfully waited for mq not full */ + { + /* Allocate the message */ + + irqrestore(saved_state); + mqmsg = mq_msgalloc(); + } + else + { + /* We cannot send the message (and didn't even try to allocate it) + * because: + * - We are not in an interrupt handler AND + * - The message queue is full AND + * - When we tried waiting, the wait was unsuccessful. + */ + + irqrestore(saved_state); + } + + /* Check if we were able to get a message structure -- this can fail + * either because we cannot send the message (and didn't bother trying + * to allocate it) or because the allocation failed. + */ + + if (mqmsg) + { + /* Yes, perform the message send. */ + + ret = mq_dosend(mqdes, mqmsg, msg, msglen, prio); + } + + sched_unlock(); + return ret; +} + diff --git a/nuttx/sched/mq_sndinternal.c b/nuttx/sched/mq_sndinternal.c new file mode 100644 index 000000000..51f898875 --- /dev/null +++ b/nuttx/sched/mq_sndinternal.c @@ -0,0 +1,455 @@ +/**************************************************************************** + * sched/mq_send.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "os_internal.h" +#ifndef CONFIG_DISABLE_SIGNALS +# include "sig_internal.h" +#endif +#include "mq_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mq_verifysend + * + * Description: + * This is internal, common logic shared by both mq_send and mq_timesend. + * This function verifies the input parameters that are common to both + * functions. + * + * Parameters: + * mqdes - Message queue descriptor + * msg - Message to send + * msglen - The length of the message in bytes + * prio - The priority of the message + * + * Return Value: + * One success, 0 (OK) is returned. On failure, -1 (ERROR) is returned and + * the errno is set appropriately: + * + * EINVAL Either msg or mqdes is NULL or the value of prio is invalid. + * EPERM Message queue opened not opened for writing. + * EMSGSIZE 'msglen' was greater than the maxmsgsize attribute of the + * message queue. + * + * Assumptions: + * + ****************************************************************************/ + +int mq_verifysend(mqd_t mqdes, const void *msg, size_t msglen, int prio) +{ + /* Verify the input parameters */ + + if (!msg || !mqdes || prio < 0 || prio > MQ_PRIO_MAX) + { + set_errno(EINVAL); + return ERROR; + } + + if ((mqdes->oflags & O_WROK) == 0) + { + set_errno(EPERM); + return ERROR; + } + + if (msglen < 0 || msglen > (size_t)mqdes->msgq->maxmsgsize) + { + set_errno(EMSGSIZE); + return ERROR; + } + + return OK; +} + +/**************************************************************************** + * Name: mq_msgalloc + * + * Description: + * The mq_msgalloc function will get a free message for use by the + * operating system. The message will be allocated from the g_msgfree + * list. + * + * If the list is empty AND the message is NOT being allocated from the + * interrupt level, then the message will be allocated. If a message + * cannot be obtained, the operating system is dead and therefore cannot + * continue. + * + * If the list is empty AND the message IS being allocated from the + * interrupt level. This function will attempt to get a message from + * the g_msgfreeirq list. If this is unsuccessful, the calling interrupt + * handler will be notified. + * + * Inputs: + * None + * + * Return Value: + * A reference to the allocated msg structure. On a failure to allocate, + * this function PANICs. + * + ****************************************************************************/ + +FAR mqmsg_t *mq_msgalloc(void) +{ + FAR mqmsg_t *mqmsg; + irqstate_t saved_state; + + /* If we were called from an interrupt handler, then try to get the message + * from generally available list of messages. If this fails, then try the + * list of messages reserved for interrupt handlers + */ + + if (up_interrupt_context()) + { + /* Try the general free list */ + + mqmsg = (FAR mqmsg_t*)sq_remfirst(&g_msgfree); + if (!mqmsg) + { + /* Try the free list reserved for interrupt handlers */ + + mqmsg = (FAR mqmsg_t*)sq_remfirst(&g_msgfreeirq); + } + } + + /* We were not called from an interrupt handler. */ + + else + { + /* Try to get the message from the generally available free list. + * Disable interrupts -- we might be called from an interrupt handler. + */ + + saved_state = irqsave(); + mqmsg = (FAR mqmsg_t*)sq_remfirst(&g_msgfree); + irqrestore(saved_state); + + /* If we cannot a message from the free list, then we will have to allocate one. */ + + if (!mqmsg) + { + mqmsg = (FAR mqmsg_t *)kmalloc((sizeof (mqmsg_t))); + + /* Check if we got an allocated message */ + + if (mqmsg) + { + mqmsg->type = MQ_ALLOC_DYN; + } + + /* No? We are dead */ + + else + { + sdbg("Out of messages\n"); + PANIC((uint32_t)OSERR_OUTOFMESSAGES); + } + } + } + + return mqmsg; +} + +/**************************************************************************** + * Name: mq_waitsend + * + * Description: + * This is internal, common logic shared by both mq_send and mq_timesend. + * This function waits until the message queue is not full. + * + * Parameters: + * mqdes - Message queue descriptor + * + * Return Value: + * On success, mq_send() returns 0 (OK); on error, -1 (ERROR) is + * returned, with errno set to indicate the error: + * + * EAGAIN The queue was empty, and the O_NONBLOCK flag was set for the + * message queue description referred to by mqdes. + * EINTR The call was interrupted by a signal handler. + * ETIMEOUT A timeout expired before the message queue became non-full + * (mq_timedsend only). + * + * Assumptions/restrictions: + * - The caller has verified the input parameters using mq_verifysend(). + * - Interrupts are disabled. + * + ****************************************************************************/ + +int mq_waitsend(mqd_t mqdes) +{ + FAR _TCB *rtcb; + FAR msgq_t *msgq; + + /* Get a pointer to the message queue */ + + msgq = mqdes->msgq; + + /* Verify that the queue is indeed full as the caller thinks */ + + if (msgq->nmsgs >= msgq->maxmsgs) + { + /* Should we block until there is sufficient space in the + * message queue? + */ + + if ((mqdes->oflags & O_NONBLOCK) != 0) + { + /* No... We will return an error to the caller. */ + + set_errno(EAGAIN); + return ERROR; + } + + /* Yes... We will not return control until the message queue is + * available or we receive a signal or at timout occurs. + */ + + else + { + /* Loop until there are fewer than max allowable messages in the + * receiving message queue + */ + + while (msgq->nmsgs >= msgq->maxmsgs) + { + /* Block until the message queue is no longer full. + * When we are unblocked, we will try again + */ + + rtcb = (FAR _TCB*)g_readytorun.head; + rtcb->msgwaitq = msgq; + msgq->nwaitnotfull++; + + set_errno(OK); + up_block_task(rtcb, TSTATE_WAIT_MQNOTFULL); + + /* When we resume at this point, either (1) the message queue + * is no longer empty, or (2) the wait has been interrupted by + * a signal. We can detect the latter case be examining the + * errno value (should be EINTR or ETIMEOUT). + */ + + if (get_errno() != OK) + { + return ERROR; + } + } + } + } + return OK; +} + +/**************************************************************************** + * Name: mq_dosend + * + * Description: + * This is internal, common logic shared by both mq_send and mq_timesend. + * This function adds the specificied message (msg) to the message queue + * (mqdes). Then it notifies any tasks that were waiting for message + * queue notifications setup by mq_notify. And, finally, it awakens any + * tasks that were waiting for the message not empty event. + * + * Parameters: + * mqdes - Message queue descriptor + * msg - Message to send + * msglen - The length of the message in bytes + * prio - The priority of the message + * + * Return Value: + * This function always returns OK. + * + * Assumptions/restrictions: + * + ****************************************************************************/ + +int mq_dosend(mqd_t mqdes, FAR mqmsg_t *mqmsg, const void *msg, size_t msglen, int prio) +{ + FAR _TCB *btcb; + FAR msgq_t *msgq; + FAR mqmsg_t *next; + FAR mqmsg_t *prev; + irqstate_t saved_state; + + /* Get a pointer to the message queue */ + + sched_lock(); + msgq = mqdes->msgq; + + /* Construct the message header info */ + + mqmsg->priority = prio; + mqmsg->msglen = msglen; + + /* Copy the message data into the message */ + + memcpy((void*)mqmsg->mail, (const void*)msg, msglen); + + /* Insert the new message in the message queue */ + + saved_state = irqsave(); + + /* Search the message list to find the location to insert the new + * message. Each is list is maintained in ascending priority order. + */ + + for (prev = NULL, next = (FAR mqmsg_t*)msgq->msglist.head; + next && prio <= next->priority; + prev = next, next = next->next); + + /* Add the message at the right place */ + + if (prev) + { + sq_addafter((FAR sq_entry_t*)prev, (FAR sq_entry_t*)mqmsg, + &msgq->msglist); + } + else + { + sq_addfirst((FAR sq_entry_t*)mqmsg, &msgq->msglist); + } + + /* Increment the count of messages in the queue */ + + msgq->nmsgs++; + irqrestore(saved_state); + + /* Check if we need to notify any tasks that are attached to the + * message queue + */ + +#ifndef CONFIG_DISABLE_SIGNALS + if (msgq->ntmqdes) + { + /* Remove the message notification data from the message queue. */ + +#ifdef CONFIG_CAN_PASS_STRUCTS + union sigval value = msgq->ntvalue; +#else + void *sival_ptr = msgq->ntvalue.sival_ptr; +#endif + int signo = msgq->ntsigno; + int pid = msgq->ntpid; + + /* Detach the notification */ + + msgq->ntpid = INVALID_PROCESS_ID; + msgq->ntsigno = 0; + msgq->ntvalue.sival_int = 0; + msgq->ntmqdes = NULL; + + /* Queue the signal -- What if this returns an error? */ + +#ifdef CONFIG_CAN_PASS_STRUCTS + sig_mqnotempty(pid, signo, value); +#else + sig_mqnotempty(pid, signo, sival_ptr); +#endif + } +#endif + + /* Check if any tasks are waiting for the MQ not empty event. */ + + saved_state = irqsave(); + if (msgq->nwaitnotempty > 0) + { + /* Find the highest priority task that is waiting for + * this queue to be non-empty in g_waitingformqnotempty + * list. sched_lock() should give us sufficent protection since + * interrupts should never cause a change in this list + */ + + for (btcb = (FAR _TCB*)g_waitingformqnotempty.head; + btcb && btcb->msgwaitq != msgq; + btcb = btcb->flink); + + /* If one was found, unblock it */ + + if (!btcb) + { + PANIC(OSERR_MQNONEMPTYCOUNT); + } + else + { + btcb->msgwaitq = NULL; + msgq->nwaitnotempty--; + up_unblock_task(btcb); + } + } + + irqrestore(saved_state); + sched_unlock(); + return OK; +} + diff --git a/nuttx/sched/mq_timedreceive.c b/nuttx/sched/mq_timedreceive.c new file mode 100644 index 000000000..0df904830 --- /dev/null +++ b/nuttx/sched/mq_timedreceive.c @@ -0,0 +1,303 @@ +/**************************************************************************** + * sched/mq_timedreceive.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "os_internal.h" +#include "clock_internal.h" +#include "mq_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mq_rcvtimeout + * + * Description: + * This function is called if the timeout elapses before the message queue + * becomes non-empty. + * + * Parameters: + * argc - the number of arguments (should be 1) + * pid - the task ID of the task to wakeup + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void mq_rcvtimeout(int argc, uint32_t pid) +{ + FAR _TCB *wtcb; + irqstate_t saved_state; + + /* Disable interrupts. This is necessary because an interrupt handler may + * attempt to send a message while we are doing this. + */ + + saved_state = irqsave(); + + /* Get the TCB associated with this pid. It is possible that task may no + * longer be active when this watchdog goes off. + */ + + wtcb = sched_gettcb((pid_t)pid); + + /* It is also possible that an interrupt/context switch beat us to the + * punch and already changed the task's state. + */ + + if (wtcb && wtcb->task_state == TSTATE_WAIT_MQNOTEMPTY) + { + /* Restart with task with a timeout error */ + + mq_waitirq(wtcb, ETIMEDOUT); + } + + /* Interrupts may now be re-enabled. */ + + irqrestore(saved_state); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mq_timedreceive + * + * Description: + * This function receives the oldest of the highest priority messages from + * the message queue specified by "mqdes." If the size of the buffer in + * bytes (msglen) is less than the "mq_msgsize" attribute of the message + * queue, mq_timedreceive will return an error. Otherwise, the selected + * message is removed from the queue and copied to "msg." + * + * If the message queue is empty and O_NONBLOCK was not set, + * mq_timedreceive() will block until a message is added to the message + * queue (or until a timeout occurs). If more than one task is waiting + * to receive a message, only the task with the highest priority that has + * waited the longest will be unblocked. + * + * mq_timedreceive() behaves just like mq_receive(), except that if the + * queue is empty and the O_NONBLOCK flag is not enabled for the message + * queue description, then abstime points to a structure which specifies a + * ceiling on the time for which the call will block. This ceiling is an + * absolute timeout in seconds and nanoseconds since the Epoch (midnight + * on the morning of 1 January 1970). + * + * If no message is available, and the timeout has already expired by the + * time of the call, mq_timedreceive() returns immediately. + * + * Parameters: + * mqdes - Message Queue Descriptor + * msg - Buffer to receive the message + * msglen - Size of the buffer in bytes + * prio - If not NULL, the location to store message priority. + * abstime - the absolute time to wait until a timeout is declared. + * + * Return Value: + * One success, the length of the selected message in bytes is returned. + * On failure, -1 (ERROR) is returned and the errno is set appropriately: + * + * EAGAIN The queue was empty, and the O_NONBLOCK flag was set + * for the message queue description referred to by 'mqdes'. + * EPERM Message queue opened not opened for reading. + * EMSGSIZE 'msglen' was less than the maxmsgsize attribute of the + * message queue. + * EINTR The call was interrupted by a signal handler. + * EINVAL Invalid 'msg' or 'mqdes' or 'abstime' + * ETIMEDOUT The call timed out before a message could be transferred. + * + * Assumptions: + * + ****************************************************************************/ + +ssize_t mq_timedreceive(mqd_t mqdes, void *msg, size_t msglen, + int *prio, const struct timespec *abstime) +{ + WDOG_ID wdog; + FAR mqmsg_t *mqmsg; + irqstate_t saved_state; + int ret = ERROR; + + DEBUGASSERT(up_interrupt_context() == false); + + /* Verify the input parameters and, in case of an error, set + * errno appropriately. + */ + + if (mq_verifyreceive(mqdes, msg, msglen) != OK) + { + return ERROR; + } + + if (!abstime || abstime->tv_sec < 0 || abstime->tv_nsec > 1000000000) + { + set_errno(EINVAL); + return ERROR; + } + + /* Create a watchdog. We will not actually need this watchdog + * unless the queue is not empty, but we will reserve it up front + * before we enter the following critical section. + */ + + wdog = wd_create(); + if (!wdog) + { + set_errno(EINVAL); + return ERROR; + } + + /* Get the next mesage from the message queue. We will disable + * pre-emption until we have completed the message received. This + * is not too bad because if the receipt takes a long time, it will + * be because we are blocked waiting for a message and pre-emption + * will be re-enabled while we are blocked + */ + + sched_lock(); + + /* Furthermore, mq_waitreceive() expects to have interrupts disabled + * because messages can be sent from interrupt level. + */ + + saved_state = irqsave(); + + /* Check if the message queue is empty. If it is NOT empty, then we + * will not need to start timer. + */ + + if (mqdes->msgq->msglist.head == NULL) + { + int ticks; + + /* Convert the timespec to clock ticks. We must have interrupts + * disabled here so that this time stays valid until the wait begins. + */ + + int result = clock_abstime2ticks(CLOCK_REALTIME, abstime, &ticks); + + /* If the time has already expired and the message queue is empty, + * return immediately. + */ + + if (result == OK && ticks <= 0) + { + result = ETIMEDOUT; + } + + /* Handle any time-related errors */ + + if (result != OK) + { + set_errno(result); + irqrestore(saved_state); + sched_unlock(); + wd_delete(wdog); + return ERROR; + } + + /* Start the watchdog */ + + wd_start(wdog, ticks, (wdentry_t)mq_rcvtimeout, 1, getpid()); + } + + /* Get the message from the message queue */ + + mqmsg = mq_waitreceive(mqdes); + + /* Stop the watchdog timer (this is not harmful in the case where + * it was never started) + */ + + wd_cancel(wdog); + + /* We can now restore interrupts */ + + irqrestore(saved_state); + + /* Check if we got a message from the message queue. We might + * not have a message if: + * + * - The message queue is empty and O_NONBLOCK is set in the mqdes + * - The wait was interrupted by a signal + * - The watchdog timeout expired + */ + + if (mqmsg) + { + ret = mq_doreceive(mqdes, mqmsg, msg, prio); + } + + sched_unlock(); + wd_delete(wdog); + return ret; +} diff --git a/nuttx/sched/mq_timedsend.c b/nuttx/sched/mq_timedsend.c new file mode 100644 index 000000000..745cc6272 --- /dev/null +++ b/nuttx/sched/mq_timedsend.c @@ -0,0 +1,319 @@ +/**************************************************************************** + * sched/mq_timedsend.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "clock_internal.h" +#include "os_internal.h" +#include "mq_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mq_sndtimeout + * + * Description: + * This function is called if the timeout elapses before the message queue + * becomes non-full. + * + * Parameters: + * argc - the number of arguments (should be 1) + * pid - the task ID of the task to wakeup + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void mq_sndtimeout(int argc, uint32_t pid) +{ + FAR _TCB *wtcb; + irqstate_t saved_state; + + /* Disable interrupts. This is necessary because an interrupt handler may + * attempt to send a message while we are doing this. + */ + + saved_state = irqsave(); + + /* Get the TCB associated with this pid. It is possible that task may no + * longer be active when this watchdog goes off. + */ + + wtcb = sched_gettcb((pid_t)pid); + + /* It is also possible that an interrupt/context switch beat us to the + * punch and already changed the task's state. + */ + + if (wtcb && wtcb->task_state == TSTATE_WAIT_MQNOTFULL) + { + /* Restart with task with a timeout error */ + + mq_waitirq(wtcb, ETIMEDOUT); + } + + /* Interrupts may now be re-enabled. */ + + irqrestore(saved_state); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mq_send + * + * Description: + * This function adds the specificied message (msg) to the message queue + * (mqdes). The "msglen" parameter specifies the length of the message + * in bytes pointed to by "msg." This length must not exceed the maximum + * message length from the mq_getattr(). + * + * If the message queue is not full, mq_timedsend() place the message in the + * message queue at the position indicated by the "prio" argrument. + * Messages with higher priority will be inserted before lower priority + * messages. The value of "prio" must not exceed MQ_PRIO_MAX. + * + * If the specified message queue is full and O_NONBLOCK is not set in the + * message queue, then mq_timedsend() will block until space becomes available + * to the queue the message or a timeout occurs. + * + * mq_timedsend() behaves just like mq_send(), except that if the queue + * is full and the O_NONBLOCK flag is not enabled for the message queue + * description, then abstime points to a structure which specifies a + * ceiling on the time for which the call will block. This ceiling is an + * absolute timeout in seconds and nanoseconds since the Epoch (midnight + * on the morning of 1 January 1970). + * + * If the message queue is full, and the timeout has already expired by + * the time of the call, mq_timedsend() returns immediately. + * + * Parameters: + * mqdes - Message queue descriptor + * msg - Message to send + * msglen - The length of the message in bytes + * prio - The priority of the message + * abstime - the absolute time to wait until a timeout is decleared + * + * Return Value: + * On success, mq_send() returns 0 (OK); on error, -1 (ERROR) + * is returned, with errno set to indicate the error: + * + * EAGAIN The queue was empty, and the O_NONBLOCK flag was set for the + * message queue description referred to by mqdes. + * EINVAL Either msg or mqdes is NULL or the value of prio is invalid. + * EPERM Message queue opened not opened for writing. + * EMSGSIZE 'msglen' was greater than the maxmsgsize attribute of the + * message queue. + * EINTR The call was interrupted by a signal handler. + * + * Assumptions/restrictions: + * + ****************************************************************************/ + +int mq_timedsend(mqd_t mqdes, const char *msg, size_t msglen, int prio, + const struct timespec *abstime) +{ + WDOG_ID wdog; + FAR msgq_t *msgq; + FAR mqmsg_t *mqmsg = NULL; + irqstate_t saved_state; + int ret = ERROR; + + DEBUGASSERT(up_interrupt_context() == false); + + /* Verify the input parameters -- setting errno appropriately + * on any failures to verify. + */ + + if (mq_verifysend(mqdes, msg, msglen, prio) != OK) + { + return ERROR; + } + + if (!abstime || abstime->tv_sec < 0 || abstime->tv_nsec > 1000000000) + { + set_errno(EINVAL); + return ERROR; + } + + /* Get a pointer to the message queue */ + + msgq = mqdes->msgq; + + /* Create a watchdog. We will not actually need this watchdog + * unless the queue is full, but we will reserve it up front + * before we enter the following critical section. + */ + + wdog = wd_create(); + if (!wdog) + { + set_errno(EINVAL); + return ERROR; + } + + /* Allocate a message structure: + * - If we are called from an interrupt handler, or + * - If the message queue is not full, or + */ + + sched_lock(); + saved_state = irqsave(); + if (up_interrupt_context() || /* In an interrupt handler */ + msgq->nmsgs < msgq->maxmsgs) /* OR Message queue not full */ + { + /* Allocate the message */ + + irqrestore(saved_state); + mqmsg = mq_msgalloc(); + } + else + { + int ticks; + + /* We are not in an interupt handler and the message queue is full. + * set up a timed wait for the message queue to become non-full. + * + * Convert the timespec to clock ticks. We must have interrupts + * disabled here so that this time stays valid until the wait begins. + */ + + int result = clock_abstime2ticks(CLOCK_REALTIME, abstime, &ticks); + + /* If the time has already expired and the message queue is empty, + * return immediately. + */ + + if (result == OK && ticks <= 0) + { + result = ETIMEDOUT; + } + + /* Handle any time-related errors */ + + if (result != OK) + { + set_errno(result); + ret = ERROR; + } + + /* Start the watchdog and begin the wait for MQ not full */ + + if (result == OK) + { + /* Start the watchdog */ + + wd_start(wdog, ticks, (wdentry_t)mq_sndtimeout, 1, getpid()); + + /* And wait for the message queue to be non-empty */ + + ret = mq_waitsend(mqdes); + + /* This may return with an error and errno set to either EINTR + * or ETIMEOUT. Cancel the watchdog timer in any event. + */ + + wd_cancel(wdog); + } + + /* That is the end of the atomic operations */ + + irqrestore(saved_state); + + /* If any of the above failed, set the errno. Otherwise, there should + * be space for another message in the message queue. NOW we can allocate + * the message structure. + */ + + if (ret == OK) + { + mqmsg = mq_msgalloc(); + } + } + + /* Check if we were able to get a message structure -- this can fail + * either because we cannot send the message (and didn't bother trying + * to allocate it) or because the allocation failed. + */ + + if (mqmsg) + { + /* Yes, peform the message send. */ + + ret = mq_dosend(mqdes, mqmsg, msg, msglen, prio); + } + + sched_unlock(); + wd_delete(wdog); + return ret; +} + diff --git a/nuttx/sched/mq_unlink.c b/nuttx/sched/mq_unlink.c new file mode 100644 index 000000000..1fa25dfa8 --- /dev/null +++ b/nuttx/sched/mq_unlink.c @@ -0,0 +1,146 @@ +/************************************************************************ + * sched.mq_unlink.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include + +#include "os_internal.h" +#include "mq_internal.h" + +/************************************************************************ + * Pre-processor Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: mq_unlink + * + * Description: + * This function removes the message queue named by "mq_name." If one + * or more tasks have the message queue open when mq_unlink() is called, + * removal of the message queue is postponed until all references to the + * message queue have been closed. + * + * Parameters: + * mq_name - Name of the message queue + * + * Return Value: + * None + * + * Assumptions: + * + ************************************************************************/ + +int mq_unlink(const char *mq_name) +{ + FAR msgq_t *msgq; + irqstate_t saved_state; + int ret = ERROR; + + /* Verify the input values */ + + if (mq_name) + { + sched_lock(); + + /* Find the named message queue */ + + msgq = mq_findnamed(mq_name); + if (msgq) + { + /* If it is no longer connected, then we can just + * discard the message queue now. + */ + + if (!msgq->nconnect) + { + /* Remove the message queue from the list of all + * message queues + */ + + saved_state = irqsave(); + (void)sq_rem((FAR sq_entry_t*)msgq, &g_msgqueues); + irqrestore(saved_state); + + /* Then deallocate it (and any messages left in it) */ + + mq_msgqfree(msgq); + } + + /* If the message queue is still connected to a message descriptor, + * then mark it for deletion when the last message descriptor is + * closed + */ + + else + { + msgq->unlinked = true; + } + + ret = OK; + } + + sched_unlock(); + } + + return ret; +} + diff --git a/nuttx/sched/mq_waitirq.c b/nuttx/sched/mq_waitirq.c new file mode 100644 index 000000000..94a15df3c --- /dev/null +++ b/nuttx/sched/mq_waitirq.c @@ -0,0 +1,172 @@ +/**************************************************************************** + * sched/mq_waitirq.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include + +#include +#include + +#include "os_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sem_waitirq + * + * Description: + * This function is called when a signal or a timeout is received by a + * task that is waiting on a message queue -- either for a queue to + * becoming not full (on mq_send) or not empty (on mq_receive). + * + * Parameters: + * wtcb - A pointer to the TCB of the task that is waiting on a message + * queue, but has received a signal instead. + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +void mq_waitirq(FAR _TCB *wtcb, int errcode) +{ + FAR msgq_t *msgq; + irqstate_t saved_state; + + /* Disable interrupts. This is necessary because an interrupt handler may + * attempt to send a message while we are doing this. + */ + + saved_state = irqsave(); + + /* It is possible that an interrupt/context switch beat us to the punch and + * already changed the task's state. NOTE: The operations within the if + * are safe because interrupts are always disabled with the msgwaitq, + * nwaitnotempty, and nwaitnotfull fields are modified. + */ + + if (wtcb->task_state == TSTATE_WAIT_MQNOTEMPTY || + wtcb->task_state == TSTATE_WAIT_MQNOTFULL) + { + /* Get the message queue associated with the waiter from the TCB */ + + msgq = wtcb->msgwaitq; +#ifdef CONFIG_DEBUG + if (!msgq) + { + /* In these states there must always be an associated message queue */ + + PANIC((uint32_t)OSERR_MQNOWAITER); + } +#endif + wtcb->msgwaitq = NULL; + + /* Decrement the count of waiters and cancel the wait */ + + if (wtcb->task_state == TSTATE_WAIT_MQNOTEMPTY) + { +#ifdef CONFIG_DEBUG + if (msgq->nwaitnotempty <= 0) + { + /* This state, there should be a positive, non-zero waiter + * count. + */ + + PANIC((uint32_t)OSERR_MQNONEMPTYCOUNT); + + } +#endif + msgq->nwaitnotempty--; + } + else + { +#ifdef CONFIG_DEBUG + if (msgq->nwaitnotfull <= 0) + { + /* This state, there should be a positive, non-zero waiter + * count. + */ + + PANIC((uint32_t)OSERR_MQNOTFULLCOUNT); + + } +#endif + msgq->nwaitnotfull--; + } + + /* Mark the errno value for the thread. */ + + wtcb->pterrno = errcode; + + /* Restart the task. */ + + up_unblock_task(wtcb); + } + + /* Interrupts may now be enabled. */ + + irqrestore(saved_state); +} + diff --git a/nuttx/sched/on_exit.c b/nuttx/sched/on_exit.c new file mode 100644 index 000000000..5b8be5cd1 --- /dev/null +++ b/nuttx/sched/on_exit.c @@ -0,0 +1,171 @@ +/**************************************************************************** + * sched/on_exit.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include + +#include + +#include "os_internal.h" + +#ifdef CONFIG_SCHED_ONEXIT + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: on_exit + * + * Description: + * Registers a function to be called at program exit. + * The on_exit() function registers the given function to be called + * at normal process termination, whether via exit or via return from + * the program's main(). The function is passed the status argument + * given to the last call to exit and the arg argument from on_exit(). + * + * NOTE 1: This function comes from SunOS 4, but is also present in + * libc4, libc5 and glibc. It no longer occurs in Solaris (SunOS 5). + * Avoid this function, and use the standard atexit() instead. + * + * NOTE 2: CONFIG_SCHED_ONEXIT must be defined to enable this function + * + * Limitiations in the current implementation: + * + * 1. Only a single on_exit function can be registered unless + * CONFIG_SCHED_ONEXIT_MAX defines a larger number. + * 2. on_exit functions are not inherited when a new task is + * created. + * + * Parameters: + * func - A pointer to the function to be called when the task exits. + * arg - An argument that will be provided to the on_exit() function when + * the task exits. + * + * Return Value: + * Zero on success. Non-zero on failure. + * + ****************************************************************************/ + +int on_exit(CODE void (*func)(int, FAR void *), FAR void *arg) +{ +#if defined(CONFIG_SCHED_ONEXIT_MAX) && CONFIG_SCHED_ONEXIT_MAX > 1 + _TCB *tcb = (_TCB*)g_readytorun.head; + int index; + int ret = ERROR; + + /* The following must be atomic */ + + if (func) + { + sched_lock(); + + /* Search for the first available slot. on_exit() functions are registered + * from lower to higher arry indices; they must be called in the reverse + * order of registration when task exists, i.e., from higher to lower + * indices. + */ + + available = -1; + for (index = 0; index < CONFIG_SCHED_ONEXIT_MAX; index++) + { + if (!tcb->onexitfunc[index]) + { + tcb->onexitfunc[index] = func; + tcb->onexitarg[index] = arg; + ret = OK; + break; + } + } + + sched_unlock(); + } + + return ret; +#else + _TCB *tcb = (_TCB*)g_readytorun.head; + int ret = ERROR; + + /* The following must be atomic */ + + sched_lock(); + if (func && !tcb->onexitfunc) + { + tcb->onexitfunc = func; + tcb->onexitarg = arg; + ret = OK; + } + + sched_unlock(); + return ret; +#endif +} + +#endif /* CONFIG_SCHED_ONEXIT */ + + diff --git a/nuttx/sched/os_bringup.c b/nuttx/sched/os_bringup.c new file mode 100644 index 000000000..ec6152891 --- /dev/null +++ b/nuttx/sched/os_bringup.c @@ -0,0 +1,194 @@ +/**************************************************************************** + * sched/os_bringup.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * With extensions by: + * + * Author: Uros Platise + * + * 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 + +#include +#include + +#include +#include + +#include "os_internal.h" +#ifdef CONFIG_PAGING +# include "pg_internal.h" +#endif +#ifdef CONFIG_SCHED_WORKQUEUE +# include "work_internal.h" +#endif +#ifdef CONFIG_BUILTIN_APP_START +# include "apps/apps.h" +#endif +#ifdef CONFIG_NUTTX_KERNEL +# include "arch/board/user_map.h" +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* If NuttX is built as a separately compiled module, then the the header + * file should contain the address of the user module entry point. If not + * then the default entry point is user_start. + */ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: os_bringup + * + * Description: + * Start all initial system tasks. This does the "system bring-up" after + * the conclusion of basic OS initialization. These initial system tasks + * may include: + * + * - pg_worker: The page-fault worker thread (only if CONFIG_PAGING is + * defined. + * - work_thread: The work thread. This general thread can be used to + * perform most any kind of queued work. Its primary + * function is to serve as the "bottom half" of device + * drivers. + * + * And the main application entry point. This may be one of two different + * symbols: + * + * - USER_ENTRYPOINT: This is the default entry point used for all of the + * example code in apps/examples. + * - CONFIG_BUILTIN_APP_START: The system can also be configured to start + * custom applications at however CONFIG_BUILTIN_APP_START + * is defined in the NuttX start-up file. + * + ****************************************************************************/ + +int os_bringup(void) +{ +#ifdef CONFIG_BUILTIN_APP_START + static const char *argv[3] = {NULL, "init", NULL}; +#endif + int init_taskid; + + /* Start the page fill worker kernel thread that will resolve page faults. + * This should always be the first thread started because it may have to + * resolve page faults in other threads + */ + +#ifdef CONFIG_PAGING + svdbg("Starting paging thread\n"); + + g_pgworker = KERNEL_THREAD("pgfill", CONFIG_PAGING_DEFPRIO, + CONFIG_PAGING_STACKSIZE, + (main_t)pg_worker, (const char **)NULL); + ASSERT(g_pgworker != ERROR); +#endif + + /* Start the worker thread that will serve as the device driver "bottom- + * half" and will perform misc garbage clean-up. + */ + +#ifdef CONFIG_SCHED_WORKQUEUE + svdbg("Starting worker thread\n"); + + g_work[HPWORK].pid = KERNEL_THREAD("work0", CONFIG_SCHED_WORKPRIORITY, + CONFIG_SCHED_WORKSTACKSIZE, + (main_t)work_hpthread, (const char **)NULL); + ASSERT(g_work[HPWORK].pid != ERROR); + + /* Start a lower priority worker thread for other, non-critical continuation + * tasks + */ + +#ifdef CONFIG_SCHED_LPWORK + svdbg("Starting worker thread\n"); + + g_work[LPWORK].pid = KERNEL_THREAD("work1", CONFIG_SCHED_LPWORKPRIORITY, + CONFIG_SCHED_LPWORKSTACKSIZE, + (main_t)work_lpthread, (const char **)NULL); + ASSERT(g_work[LPWORK].pid != ERROR); +#endif +#endif + + /* Once the operating system has been initialized, the system must be + * started by spawning the user init thread of execution. This is the + * first user-mode thead. + */ + + svdbg("Starting init thread\n"); + +#ifdef CONFIG_BUILTIN_APP_START + /* Start the built-in named application, passing an "init" argument, so that + * application can distinguish different run-levels + */ + + init_taskid = exec_namedapp(CONFIG_BUILTIN_APP_START, argv); +#else + /* Start the default application at CONFIG_USER_ENTRYPOINT() */ + + init_taskid = TASK_CREATE("init", SCHED_PRIORITY_DEFAULT, + CONFIG_USERMAIN_STACKSIZE, + (main_t)CONFIG_USER_ENTRYPOINT, (const char **)NULL); +#endif + ASSERT(init_taskid != ERROR); + return OK; +} diff --git a/nuttx/sched/os_internal.h b/nuttx/sched/os_internal.h new file mode 100644 index 000000000..13b8083cf --- /dev/null +++ b/nuttx/sched/os_internal.h @@ -0,0 +1,306 @@ +/**************************************************************************** + * sched/os_internal.h + * + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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. + * + ****************************************************************************/ + +#ifndef __SCHED_OS_INTERNAL_H +#define __SCHED_OS_INTERNAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* OS CRASH CODES: All must lie in the range 0-99 */ + +enum os_crash_codes_e +{ + OSERR_NOERROR = 0, /* No error */ + OSERR_NOTIMPLEMENTED, /* Feature is not implemented */ + OSERR_INTERNAL, /* Internal logic error */ + OSERR_UNEXPECTEDISR, /* Received unexpected interrupt */ + OSERR_UNDEFINEDINSN, /* Undefined instruction */ + OSERR_ERREXCEPTION, /* Other CPU-detected errors */ + OSERR_OUTOFMEMORY, /* Insufficient memory */ + OSERR_OUTOFMESSAGES, /* Out of messages */ + OSERR_NOIDLETASK, /* There is no idle task */ + OSERR_MQNONEMPTYCOUNT, /* Expected waiter for non-empty queue */ + OSERR_MQNOTFULLCOUNT, /* Expected waiter for non-full queue */ + OSERR_MQNOWAITER, /* Expected a queue for the waiter */ + OSERR_BADWAITSEM, /* Already waiting for a semaphore */ + OSERR_BADMSGTYPE, /* Tried to free a bad message type */ + OSERR_FAILEDTOADDSIGNAL, /* Failed to add pending signal */ + OSERR_FAILEDTOREMOVESIGNAL, /* Failed to remove pending signal */ + OSERR_TIMEOUTNOTCB, /* Timed out, but not TCB registered */ + OSERR_NOPENDINGSIGNAL, /* Expected a signal to be pending */ + OSERR_BADDELETESTATE, /* Bad state in task deletion */ + OSERR_WDOGNOTFOUND, /* Active watchdog not found */ + OSERR_EXITFROMINTERRUPT, /* Interrupt code attempted to exit */ + OSERR_BADUNBLOCKSTATE, /* Attempt to unblock from bad state */ + OSERR_BADBLOCKSTATE, /* Attempt to block from bad state */ + OSERR_BADREPRIORITIZESTATE /* Attempt to reprioritize in bad state or priority */ +}; + +/* Special task IDS */ + +#define NULL_TASK_PROCESS_ID 0 +#define INVALID_PROCESS_ID 0 + +/* Although task IDs can take the (positive, non-zero) + * range of pid_t, the number of tasks that will be supported + * at any one time is (artificially) limited by the CONFIG_MAX_TASKS + * configuration setting. Limiting the number of tasks speeds certain + * OS functions (this is the only limitation in the number of + * tasks built into the design). + */ + +#define MAX_TASKS_MASK (CONFIG_MAX_TASKS-1) +#define PIDHASH(pid) ((pid) & MAX_TASKS_MASK) + +/* Stubs used when there are no file descriptors */ + +#if CONFIG_NFILE_DESCRIPTORS <= 0 && CONFIG_NSOCKET_DESCRIPTORS <= 0 +# define sched_setupidlefiles(t) (OK) +# define sched_setuptaskfiles(t) (OK) +# define sched_setuppthreadfiles(t) (OK) +# define sched_releasefiles(t) (OK) +#endif + +/* One processor family supported by NuttX has a single, fixed hardware stack. + * That is the 8051 family. So for that family only, there is a variant form + * of kernel_thread() that does not take a stack size parameter. The following + * helper macro is provided to work around the ugliness of that exception. + */ + +#ifndef CONFIG_CUSTOM_STACK +# define KERNEL_THREAD(n,p,s,e,a) kernel_thread(n,p,s,e,a) +#else +# define KERNEL_THREAD(n,p,s,e,a) kernel_thread(n,p,e,a) +#endif + +/* A more efficient ways to access the errno */ + +#define SET_ERRNO(e) \ + { _TCB *rtcb = _TCB*)g_readytorun.head; rtcb->pterrno = (e); } + +#define _SET_TCB_ERRNO(t,e) \ + { (t)->pterrno = (e); } + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + +/* This structure defines the format of the hash table that + * is used to (1) determine if a task ID is unique, and (2) + * to map a process ID to its corresponding TCB. + */ + +struct pidhash_s +{ + FAR _TCB *tcb; + pid_t pid; +}; + +typedef struct pidhash_s pidhash_t; + +/* This structure defines an element of the g_tasklisttable[]. + * This table is used to map a task_state enumeration to the + * corresponding task list. + */ + +struct tasklist_s +{ + DSEG volatile dq_queue_t *list; /* Pointer to the task list */ + bool prioritized; /* true if the list is prioritized */ +}; + +typedef struct tasklist_s tasklist_t; + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/* Declared in os_start.c ***************************************************/ + +/* The state of a task is indicated both by the task_state field of the TCB + * and by a series of task lists. All of these tasks lists are declared + * below. Although it is not always necessary, most of these lists are + * prioritized so that common list handling logic can be used (only the + * g_readytorun, the g_pendingtasks, and the g_waitingforsemaphore lists need + * to be prioritized). + */ + +/* This is the list of all tasks that are ready to run. The head of this + * list is the currently active task; the tail of this list is always the + * IDLE task. + */ + +extern volatile dq_queue_t g_readytorun; + +/* This is the list of all tasks that are ready-to-run, but cannot be placed + * in the g_readytorun list because: (1) They are higher priority than the + * currently active task at the head of the g_readytorun list, and (2) the + * currently active task has disabled pre-emption. + */ + +extern volatile dq_queue_t g_pendingtasks; + +/* This is the list of all tasks that are blocked waiting for a semaphore */ + +extern volatile dq_queue_t g_waitingforsemaphore; + +/* This is the list of all tasks that are blocked waiting for a signal */ + +#ifndef CONFIG_DISABLE_SIGNALS +extern volatile dq_queue_t g_waitingforsignal; +#endif + +/* This is the list of all tasks that are blocked waiting for a message + * queue to become non-empty. + */ + +#ifndef CONFIG_DISABLE_MQUEUE +extern volatile dq_queue_t g_waitingformqnotempty; +#endif + +/* This is the list of all tasks that are blocked waiting for a message + * queue to become non-full. + */ + +#ifndef CONFIG_DISABLE_MQUEUE +extern volatile dq_queue_t g_waitingformqnotfull; +#endif + +/* This is the list of all tasks that are blocking waiting for a page fill */ + +#ifdef CONFIG_PAGING +extern volatile dq_queue_t g_waitingforfill; +#endif + +/* This the list of all tasks that have been initialized, but not yet + * activated. NOTE: This is the only list that is not prioritized. + */ + +extern volatile dq_queue_t g_inactivetasks; + +/* This is the list of dayed memory deallocations that need to be handled + * within the IDLE loop. These deallocations get queued by sched_free() + * if the OS attempts to deallocate memory while it is within an interrupt + * handler. + */ + +extern volatile sq_queue_t g_delayeddeallocations; + +/* This is the value of the last process ID assigned to a task */ + +extern volatile pid_t g_lastpid; + +/* The following hash table is used for two things: + * + * 1. This hash table greatly speeds the determination of a new unique + * process ID for a task, and + * 2. Is used to quickly map a process ID into a TCB. + * + * It has the side effects of using more memory and limiting the number + * of tasks to CONFIG_MAX_TASKS. + */ + +extern pidhash_t g_pidhash[CONFIG_MAX_TASKS]; + +/* This is a table of task lists. This table is indexed by the task state + * enumeration type (tstate_t) and provides a pointer to the associated + * static task list (if there is one) as well as a boolean indication as to + * if the list is an ordered list or not. + */ + +extern const tasklist_t g_tasklisttable[NUM_TASK_STATES]; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +int os_bringup(void); +void task_start(void); +int task_schedsetup(FAR _TCB *tcb, int priority, start_t start, + main_t main); +int task_argsetup(FAR _TCB *tcb, FAR const char *name, FAR const char *argv[]); +void task_exithook(FAR _TCB *tcb, int status); +int task_deletecurrent(void); +#ifndef CONFIG_CUSTOM_STACK +int kernel_thread(FAR const char *name, int priority, int stack_size, + main_t entry, FAR const char *argv[]); +#else +int kernel_thread(FAR const char *name, int priority, main_t entry, + FAR const char *argv[]); +#endif +bool sched_addreadytorun(FAR _TCB *rtrtcb); +bool sched_removereadytorun(FAR _TCB *rtrtcb); +bool sched_addprioritized(FAR _TCB *newTcb, DSEG dq_queue_t *list); +bool sched_mergepending(void); +void sched_addblocked(FAR _TCB *btcb, tstate_t task_state); +void sched_removeblocked(FAR _TCB *btcb); +int sched_setpriority(FAR _TCB *tcb, int sched_priority); +#ifdef CONFIG_PRIORITY_INHERITANCE +int sched_reprioritize(FAR _TCB *tcb, int sched_priority); +#else +# define sched_reprioritize(tcb,sched_priority) sched_setpriority(tcb,sched_priority) +#endif +FAR _TCB *sched_gettcb(pid_t pid); +bool sched_verifytcb(FAR _TCB *tcb); + +#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0 +int sched_setupidlefiles(FAR _TCB *tcb); +int sched_setuptaskfiles(FAR _TCB *tcb); +int sched_setuppthreadfiles(FAR _TCB *tcb); +#if CONFIG_NFILE_STREAMS > 0 +int sched_setupstreams(FAR _TCB *tcb); +#endif +int sched_releasefiles(FAR _TCB *tcb); +#endif + +int sched_releasetcb(FAR _TCB *tcb); +void sched_garbagecollection(void); + +#endif /* __SCHED_OS_INTERNAL_H */ diff --git a/nuttx/sched/os_start.c b/nuttx/sched/os_start.c new file mode 100644 index 000000000..c0b16236d --- /dev/null +++ b/nuttx/sched/os_start.c @@ -0,0 +1,466 @@ +/**************************************************************************** + * sched/os_start.c + * + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "os_internal.h" +#include "sig_internal.h" +#include "wd_internal.h" +#include "sem_internal.h" +#ifndef CONFIG_DISABLE_MQUEUE +# include "mq_internal.h" +#endif +#ifndef CONFIG_DISABLE_PTHREAD +# include "pthread_internal.h" +#endif +#include "clock_internal.h" +#include "timer_internal.h" +#include "irq_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/* Task Lists ***************************************************************/ +/* The state of a task is indicated both by the task_state field of the TCB + * and by a series of task lists. All of these tasks lists are declared + * below. Although it is not always necessary, most of these lists are + * prioritized so that common list handling logic can be used (only the + * g_readytorun, the g_pendingtasks, and the g_waitingforsemaphore lists need + * to be prioritized). + */ + +/* This is the list of all tasks that are ready to run. The head of this + * list is the currently active task; the tail of this list is always the + * IDLE task. + */ + +volatile dq_queue_t g_readytorun; + +/* This is the list of all tasks that are ready-to-run, but cannot be placed + * in the g_readytorun list because: (1) They are higher priority than the + * currently active task at the head of the g_readytorun list, and (2) the + * currently active task has disabled pre-emption. + */ + +volatile dq_queue_t g_pendingtasks; + +/* This is the list of all tasks that are blocked waiting for a semaphore */ + +volatile dq_queue_t g_waitingforsemaphore; + +/* This is the list of all tasks that are blocked waiting for a signal */ + +#ifndef CONFIG_DISABLE_SIGNALS +volatile dq_queue_t g_waitingforsignal; +#endif + +/* This is the list of all tasks that are blocked waiting for a message + * queue to become non-empty. + */ + +#ifndef CONFIG_DISABLE_MQUEUE +volatile dq_queue_t g_waitingformqnotempty; +#endif + +/* This is the list of all tasks that are blocked waiting for a message + * queue to become non-full. + */ + +#ifndef CONFIG_DISABLE_MQUEUE +volatile dq_queue_t g_waitingformqnotfull; +#endif + +/* This is the list of all tasks that are blocking waiting for a page fill */ + +#ifdef CONFIG_PAGING +volatile dq_queue_t g_waitingforfill; +#endif + +/* This the list of all tasks that have been initialized, but not yet + * activated. NOTE: This is the only list that is not prioritized. + */ + +volatile dq_queue_t g_inactivetasks; + +/* This is the list of dayed memory deallocations that need to be handled + * within the IDLE loop. These deallocations get queued by sched_free() + * if the OS attempts to deallocate memory while it is within an interrupt + * handler. + */ + +volatile sq_queue_t g_delayeddeallocations; + +/* This is the value of the last process ID assigned to a task */ + +volatile pid_t g_lastpid; + +/* The following hash table is used for two things: + * + * 1. This hash table greatly speeds the determination of + * a new unique process ID for a task, and + * 2. Is used to quickly map a process ID into a TCB. + * It has the side effects of using more memory and limiting + * + * the number of tasks to CONFIG_MAX_TASKS. + */ + +pidhash_t g_pidhash[CONFIG_MAX_TASKS]; + +/* This is a table of task lists. This table is indexed by + * the task state enumeration type (tstate_t) and provides + * a pointer to the associated static task list (if there + * is one) as well as a boolean indication as to if the list + * is an ordered list or not. + */ + +const tasklist_t g_tasklisttable[NUM_TASK_STATES] = +{ + { NULL, false }, /* TSTATE_TASK_INVALID */ + { &g_pendingtasks, true }, /* TSTATE_TASK_PENDING */ + { &g_readytorun, true }, /* TSTATE_TASK_READYTORUN */ + { &g_readytorun, true }, /* TSTATE_TASK_RUNNING */ + { &g_inactivetasks, false }, /* TSTATE_TASK_INACTIVE */ + { &g_waitingforsemaphore, true } /* TSTATE_WAIT_SEM */ +#ifndef CONFIG_DISABLE_SIGNALS + , + { &g_waitingforsignal, false } /* TSTATE_WAIT_SIG */ +#endif +#ifndef CONFIG_DISABLE_MQUEUE + , + { &g_waitingformqnotempty, true }, /* TSTATE_WAIT_MQNOTEMPTY */ + { &g_waitingformqnotfull, true } /* TSTATE_WAIT_MQNOTFULL */ +#endif +#ifdef CONFIG_PAGING + , + { &g_waitingforfill, true } /* TSTATE_WAIT_PAGEFILL */ +#endif +}; + +/**************************************************************************** + * Private Variables + ****************************************************************************/ +/* This is the task control block for this thread of execution. This thread + * of execution is the IDLE task. NOTE: the system boots into the IDLE + * task. The IDLE task spawns the user initialization task (user_start) and + * that user init task is responsible for bringing up the rest of the system + */ + +static FAR _TCB g_idletcb; + +/* This is the name of the idle task */ + +static FAR const char g_idlename[] = "Idle Task"; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: os_start + * + * Description: + * This function is called to initialize the operating system and to spawn + * the user initization thread of execution + * + ****************************************************************************/ + +void os_start(void) +{ + int i; + + slldbg("Entry\n"); + + /* Initialize all task lists */ + + dq_init(&g_readytorun); + dq_init(&g_pendingtasks); + dq_init(&g_waitingforsemaphore); +#ifndef CONFIG_DISABLE_SIGNALS + dq_init(&g_waitingforsignal); +#endif +#ifndef CONFIG_DISABLE_MQUEUE + dq_init(&g_waitingformqnotfull); + dq_init(&g_waitingformqnotempty); +#endif +#ifdef CONFIG_PAGING + dq_init(&g_waitingforfill); +#endif + dq_init(&g_inactivetasks); + sq_init(&g_delayeddeallocations); + + /* Initialize the logic that determine unique process IDs. */ + + g_lastpid = 0; + for (i = 0; i < CONFIG_MAX_TASKS; i++) + { + g_pidhash[i].tcb = NULL; + g_pidhash[i].pid = INVALID_PROCESS_ID; + } + + /* Assign the process ID of ZERO to the idle task */ + + g_pidhash[ PIDHASH(0)].tcb = &g_idletcb; + g_pidhash[ PIDHASH(0)].pid = 0; + + /* Initialize a TCB for this thread of execution. NOTE: The default + * value for most components of the g_idletcb are zero. The entire + * structure is set to zero. Then only the (potentially) non-zero + * elements are initialized. NOTE: The idle task is the only task in + * that has pid == 0 and sched_priority == 0. + */ + + bzero((void*)&g_idletcb, sizeof(_TCB)); + g_idletcb.task_state = TSTATE_TASK_RUNNING; + g_idletcb.entry.main = (main_t)os_start; + +#if CONFIG_TASK_NAME_SIZE > 0 + strncpy(g_idletcb.name, g_idlename, CONFIG_TASK_NAME_SIZE-1); + g_idletcb.argv[0] = g_idletcb.name; +#else + g_idletcb.argv[0] = (char*)g_idlename; +#endif /* CONFIG_TASK_NAME_SIZE */ + + /* Then add the idle task's TCB to the head of the ready to run list */ + + dq_addfirst((FAR dq_entry_t*)&g_idletcb, (FAR dq_queue_t*)&g_readytorun); + + /* Initialize the processor-specific portion of the TCB */ + + g_idletcb.flags = TCB_FLAG_TTYPE_KERNEL; + up_initial_state(&g_idletcb); + + /* Initialize the semaphore facility(if in link). This has to be done + * very early because many subsystems depend upon fully functional + * semaphores. + */ + +#ifdef CONFIG_HAVE_WEAKFUNCTIONS + if (sem_initialize != NULL) +#endif + { + sem_initialize(); + } + + /* Initialize the memory manager */ + +#ifndef CONFIG_HEAP_BASE + { + FAR void *heap_start; + size_t heap_size; + up_allocate_heap(&heap_start, &heap_size); + kmm_initialize(heap_start, heap_size); + } +#else + kmm_initialize((void*)CONFIG_HEAP_BASE, CONFIG_HEAP_SIZE); +#endif + + /* Initialize the interrupt handling subsystem (if included) */ + +#ifdef CONFIG_HAVE_WEAKFUNCTIONS + if (irq_initialize != NULL) +#endif + { + irq_initialize(); + } + + /* Initialize the watchdog facility (if included in the link) */ + +#ifdef CONFIG_HAVE_WEAKFUNCTIONS + if (wd_initialize != NULL) +#endif + { + wd_initialize(); + } + + /* Initialize the POSIX timer facility (if included in the link) */ + +#ifndef CONFIG_DISABLE_CLOCK +#ifdef CONFIG_HAVE_WEAKFUNCTIONS + if (clock_initialize != NULL) +#endif + { + clock_initialize(); + } +#endif + +#ifndef CONFIG_DISABLE_POSIX_TIMERS +#ifdef CONFIG_HAVE_WEAKFUNCTIONS + if (timer_initialize != NULL) +#endif + { + timer_initialize(); + } +#endif + + /* Initialize the signal facility (if in link) */ + +#ifndef CONFIG_DISABLE_SIGNALS +#ifdef CONFIG_HAVE_WEAKFUNCTIONS + if (sig_initialize != NULL) +#endif + { + sig_initialize(); + } +#endif + + /* Initialize the named message queue facility (if in link) */ + +#ifndef CONFIG_DISABLE_MQUEUE +#ifdef CONFIG_HAVE_WEAKFUNCTIONS + if (mq_initialize != NULL) +#endif + { + mq_initialize(); + } +#endif + + /* Initialize the thread-specific data facility (if in link) */ + +#ifndef CONFIG_DISABLE_PTHREAD +#ifdef CONFIG_HAVE_WEAKFUNCTIONS + if (pthread_initialize != NULL) +#endif + { + pthread_initialize(); + } +#endif + + /* Initialize the file system (needed to support device drivers) */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 +#ifdef CONFIG_HAVE_WEAKFUNCTIONS + if (fs_initialize != NULL) +#endif + { + fs_initialize(); + } +#endif + + /* Initialize the network system */ + +#ifdef CONFIG_NET +#if 0 + if (net_initialize != NULL) +#endif + { + net_initialize(); + } +#endif + + /* The processor specific details of running the operating system + * will be handled here. Such things as setting up interrupt + * service routines and starting the clock are some of the things + * that are different for each processor and hardware platform. + */ + + up_initialize(); + + /* Initialize the C libraries (if included in the link). This + * is done last because the libraries may depend on the above. + */ + +#ifdef CONFIG_HAVE_WEAKFUNCTIONS + if (lib_initialize != NULL) +#endif + { + lib_initialize(); + } + + /* Create stdout, stderr, stdin */ + + (void)sched_setupidlefiles(&g_idletcb); + + /* Create initial tasks and bring-up the system */ + + (void)os_bringup(); + + /* When control is return to this point, the system is idle. */ + + sdbg("Beginning Idle Loop\n"); + for (;;) + { + /* Perform garbage collection (if it is not being done by the worker + * thread). This cleans-up memory de-allocations that were queued + * because they could not be freed in that execution context (for + * example, if the memory was freed from an interrupt handler). + */ + +#ifndef CONFIG_SCHED_WORKQUEUE + /* We must have exclusive access to the memory manager to do this + * BUT the idle task cannot wait on a semaphore. So we only do + * the cleanup now if we can get the semaphore -- this should be + * possible because if the IDLE thread is running, no other task is! + */ + + if (kmm_trysemaphore() == 0) + { + sched_garbagecollection(); + kmm_givesemaphore(); + } +#endif + + /* Perform any processor-specific idle state operations */ + + up_idle(); + } +} diff --git a/nuttx/sched/pg_internal.h b/nuttx/sched/pg_internal.h new file mode 100644 index 000000000..e7bafcd91 --- /dev/null +++ b/nuttx/sched/pg_internal.h @@ -0,0 +1,126 @@ +/**************************************************************************** + * sched/pg_internal.h + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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. + * + ****************************************************************************/ + +#ifndef __SCHED_PG_INTERNAL_H +#define __SCHED_PG_INTERNAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#ifdef CONFIG_PAGING + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +/* Supply reasonable (but probably non-optimal) default settings if + * configuration items are omitted. + */ + +#ifndef CONFIG_PAGING_DEFPRIO +# define CONFIG_PAGING_DEFPRIO 50 +#endif + +#ifndef CONFIG_PAGING_WORKPERIOD +# define CONFIG_PAGING_WORKPERIOD (500*1000) /* 1/2 second */ +#endif + +#ifndef CONFIG_PAGING_STACKSIZE +# define CONFIG_PAGING_STACKSIZE CONFIG_IDLETHREAD_STACKSIZE +#endif + +#ifdef CONFIG_DISABLE_SIGNALS +# warning "Page fill support requires signals" +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY + +/* This is the task IDof the page fill worker thread. This value was set in + * os_start when the page fill worker thread was started. + */ + +extern pid_t g_pgworker; + +/* The page fill worker thread maintains a static variable called g_pftcb. + * If no page fill is in progress, g_pftcb will be NULL. Otherwise, g_pftcb + * will point to the TCB of the task which is receiving the fill that is + * in progess. + * + * NOTE: I think that this is the only state in which a TCB does not reside + * in some list. Here is it in limbo, outside of the normally queuing while + * the page file is in progress. Where here, it will be marked with + * TSTATE_TASK_INVALID. + */ + +extern FAR _TCB *g_pftcb; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: pg_worker + * + * Description: + * This is the entry point of the worker thread that performs the actual + * page file. + * + * Input parameters: + * argc, argv (not used) + * + * Returned Value: + * Does not return + * + ****************************************************************************/ + +int pg_worker(int argc, char *argv[]); + +#endif /* __ASSEMBLY__ */ +#endif /* CONFIG_PAGING */ +#endif /* __SCHED_PG_INTERNAL_H */ diff --git a/nuttx/sched/pg_miss.c b/nuttx/sched/pg_miss.c new file mode 100644 index 000000000..8a649a6d5 --- /dev/null +++ b/nuttx/sched/pg_miss.c @@ -0,0 +1,179 @@ +/**************************************************************************** + * sched/pg_miss.c + * + * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include + +#include +#include +#include + +#ifdef CONFIG_PAGING + +#include "os_internal.h" +#include "pg_internal.h" + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pg_miss + * + * Description: + * This function is called from architecture-specific memory segmentation + * fault handling logic. This function will perform the following + * operations: + * + * 1) Sanity checking. + * - ASSERT if the currently executing task is the page fill worker + * thread. The page fill worker thread is how the the page fault + * is resolved and all logic associated with the page fill worker + * must be "locked" and always present in memory. + * - ASSERT if an interrupt was executing at the time of the exception. + * 2) Block the currently executing task. + * - Call up_block_task() to block the task at the head of the ready- + * to-run list. This should cause an interrupt level context switch + * to the next highest priority task. + * - The blocked task will be marked with state TSTATE_WAIT_PAGEFILL + * and will be retained in the g_waitingforfill prioritized task + * list. + * 3) Boost the page fill worker thread priority. + * - Check the priority of the task at the head of the g_waitingforfill + * list. If the priority of that task is higher than the current + * priority of the page fill worker thread, then boost the priority + * of the page fill worker thread to that priority. + * 4) Signal the page fill worker thread. + * - Is there a page fill pending? If not then signal the worker + * thread to start working on the queued page fill requests. + * + * Input Parameters: + * None - The head of the ready-to-run list is assumed to be task that + * caused the exception. + * + * Returned Value: + * None - Either this function function succeeds or an assertion occurs. + * + * Assumptions: + * - It is assumed that this function is called from the level of an + * exception handler and that all interrupts are disabled. + * - It is assumed that currently executing task (the one at the head of + * the ready-to-run list) is the one that cause the fault. This will + * always be true unless the page fault occurred in an interrupt handler. + * Interrupt handling logic must always be present and "locked" into + * memory. + * - As mentioned above, the task causing the page fault must not be the + * page fill worker thread because that is the only way to complete the + * page fill. + * + * NOTES: + * 1. One way to accomplish this would be a two pass link phase: + * - In the first phase, create a partially linked objected containing + * all interrupt/exception handling logic, the page fill worker thread + * plus all parts of the IDLE thread (which must always be available + * for execution). + * - All of the .text and .rodata sections of this partial link should + * be collected into a single section. + * - The second link would link the partially linked object along with + * the remaining object to produce the final binary. The linker + * script should position the "special" section so that it lies + * in a reserved, "non-swappable" region. + * + ****************************************************************************/ + +void pg_miss(void) +{ + FAR _TCB *ftcb = (FAR _TCB*)g_readytorun.head; + FAR _TCB *wtcb; + + /* Sanity checking + * + * ASSERT if the currently executing task is the page fill worker thread. + * The page fill worker thread is how the the page fault is resolved and + * all logic associated with the page fill worker must be "locked" and + * always present in memory. + */ + + pglldbg("Blocking TCB: %p PID: %d\n", ftcb, ftcb->pid); + DEBUGASSERT(g_pgworker != ftcb->pid); + + /* Block the currently executing task + * - Call up_block_task() to block the task at the head of the ready- + * to-run list. This should cause an interrupt level context switch + * to the next highest priority task. + * - The blocked task will be marked with state TSTATE_WAIT_PAGEFILL + * and will be retained in the g_waitingforfill prioritized task list. + */ + + up_block_task(ftcb, TSTATE_WAIT_PAGEFILL); + + /* Boost the page fill worker thread priority. + * - Check the priority of the task at the head of the g_waitingforfill + * list. If the priority of that task is higher than the current + * priority of the page fill worker thread, then boost the priority + * of the page fill worker thread to that priority. + */ + + wtcb = sched_gettcb(g_pgworker); + DEBUGASSERT(wtcb != NULL); + + if (wtcb->sched_priority < ftcb->sched_priority) + { + /* Reprioritize the page fill worker thread */ + + pgllvdbg("New worker priority. %d->%d\n", + wtcb->sched_priority, ftcb->sched_priority); + sched_setpriority(wtcb, ftcb->sched_priority); + } + + /* Signal the page fill worker thread. + * - Is there a page fill pending? If not then signal the worker + * thread to start working on the queued page fill requests. + */ + + if (!g_pftcb) + { + pglldbg("Signaling worker. PID: %d\n", g_pgworker); + kill(g_pgworker, SIGWORK); + } +} + +#endif /* CONFIG_PAGING */ diff --git a/nuttx/sched/pg_worker.c b/nuttx/sched/pg_worker.c new file mode 100644 index 000000000..4a18ec9a3 --- /dev/null +++ b/nuttx/sched/pg_worker.c @@ -0,0 +1,678 @@ +/**************************************************************************** + * sched/pg_worker.c + * Page fill worker thread implementation. + * + * Copyright (C) 2010-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "os_internal.h" +#include "pg_internal.h" + +#ifdef CONFIG_PAGING + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +#ifdef CONFIG_DISABLE_SIGNALS +# warning "Signals needed by this function (CONFIG_DISABLE_SIGNALS=n)" +#endif + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/* This is the task ID of the page fill worker thread. This value was set in + * os_start when the page fill worker thread was started. + */ + +pid_t g_pgworker; + +/* The page fill worker thread maintains a static variable called g_pftcb. + * If no fill is in progress, g_pftcb will be NULL. Otherwise, g_pftcb will + * point to the TCB of the task which is receiving the fill that is in progess. + * + * NOTE: I think that this is the only state in which a TCB does not reside + * in some list. Here is it in limbo, outside of the normally queuing while + * the page file is in progress. Where here, it will be marked with + * TSTATE_TASK_INVALID. + */ + +FAR _TCB *g_pftcb; + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +#ifndef CONFIG_PAGING_BLOCKINGFILL + +/* When a page fill completes, the result of the fill is stored here. The + * value -EBUSY means that the page fill callback has not yet been received. + */ + +static int g_fillresult; + +/* A configurable timeout period (in clock ticks) may be select to detect + * page fill failures. + */ + +#ifdef CONFIG_PAGING_TIMEOUT_TICKS +status uint32_t g_starttime; +#endif +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pg_callback + * + * Description: + * This function is called from the architecture-specific, page fill logic + * when the page fill completes (with or without an error). A reference to + * this function was provided to up_fillpage(). The driver will provide + * the result of the fill as an argument. + * + * NOTE: pg_callback() must also be locked in memory. + * + * When pg_callback() is called, it will perform the following operations: + * + * - Verify that g_pftcb is non-NULL. + * - Find the higher priority between the task waiting for the fill to + * complete in g_pftcb and the task waiting at the head of the + * g_waitingforfill list. That will be the priority of he highest priority + * task waiting for a fill. + * - If this higher priority is higher than current page fill worker thread, + * then boost worker thread's priority to that level. Thus, the page fill + * worker thread will always run at the priority of the highest priority + * task that is waiting for a fill. + * - Signal the page fill worker thread. + * + * Input parameters: + * tcb - The TCB of the task that just received the fill. + * result - The result of the page fill operation. + * + * Returned Value: + * None + * + * Assumptions: + * Possibly executing in the context of a driver interrupt handler??? + * + ****************************************************************************/ + +#ifndef CONFIG_PAGING_BLOCKINGFILL +static void pg_callback(FAR _TCB *tcb, int result) +{ + /* Verify that g_pftcb is non-NULL */ + + pgllvdbg("g_pftcb: %p\n", g_pftcb); + if (g_pftcb) + { + FAR _TCB *htcb = (FAR _TCB *)g_waitingforfill.head; + FAR _TCB *wtcb = sched_gettcb(g_pgworker); + + /* Find the higher priority between the task waiting for the fill to + * complete in g_pftcb and the task waiting at the head of the + * g_waitingforfill list. That will be the priority of he highest + * priority task waiting for a fill. + */ + + int priority = g_pftcb->sched_priority; + if (htcb && priority < htcb->sched_priority) + { + priority = htcb->sched_priority; + } + + /* If this higher priority is higher than current page fill worker + * thread, then boost worker thread's priority to that level. Thus, + * the page fill worker thread will always run at the priority of + * the highest priority task that is waiting for a fill. + */ + + if (priority > wtcb->sched_priority) + { + pgllvdbg("New worker priority. %d->%d\n", + wtcb->sched_priority, priority); + sched_setpriority(wtcb, priority); + } + + /* Save the page fill result (don't permit the value -EBUSY) */ + + if (result == -EBUSY) + { + result = -ENOSYS; + } + + g_fillresult = result; + } + + /* Signal the page fill worker thread (in any event) */ + + pglldbg("Signaling worker. PID: %d\n", g_pgworker); + kill(g_pgworker, SIGWORK); +} +#endif + +/**************************************************************************** + * Name: pg_dequeue + * + * Description: + * Dequeue the next, highest priority TCB from the g_waitingforfill task + * list. Call up_checkmapping() see if the still needs to be performed + * for that task. In certain conditions, the page fault may occur on + * several threads for the same page and be queued multiple times. In this + * corner case, the blocked task will simply be restarted. + * + * This function will continue to examine g_waitingforfill until either + * (1) a task is found that still needs the page fill, or (2) the + * g_waitingforfill task list becomes empty. + * + * The result (NULL or a TCB pointer) will be returned in the global + * variable, g_pftcb. + * + * Input parameters: + * None + * + * Returned Value: + * If there are no further queue page fill operations to be performed, + * pg_dequeue() will return false. Otherwise, it will return + * true to that the full is in process (any errors will result in + * assertions and this function will not return). + * + * Assumptions: + * Executing in the context of the page fill worker thread with all + * interrupts disabled. + * + ****************************************************************************/ + +static inline bool pg_dequeue(void) +{ + /* Loop until either (1) the TCB of a task that requires a fill is found, OR + * (2) the g_watingforfill list becomes empty. + */ + + do + { + /* Remove the TCB from the head of the list (if any) */ + + g_pftcb = (FAR _TCB *)dq_remfirst((dq_queue_t*)&g_waitingforfill); + pgllvdbg("g_pftcb: %p\n", g_pftcb); + if (g_pftcb != NULL) + { + /* Call the architecture-specific function up_checkmapping() to see if + * the page fill still needs to be performed. In certain conditions, + * the page fault may occur on several threads for the same page and + * be queues multiple times. In this corner case, the blocked task will + * simply be restarted. + */ + + if (!up_checkmapping(g_pftcb)) + { + /* This page needs to be filled. pg_miss bumps up + * the priority of the page fill worker thread as each + * TCB is added to the g_waitingforfill list. So we + * may need to also drop the priority of the worker + * thread as the next TCB comes off of the list. + * + * If wtcb->sched_priority > CONFIG_PAGING_DEFPRIO, + * then the page fill worker thread is executing at + * an elevated priority that may be reduced. + * + * If wtcb->sched_priority > g_pftcb->sched_priority + * then the page fill worker thread is executing at + * a higher priority than is appropriate for this + * fill (this priority can get re-boosted by pg_miss() + * if a new higher priority fill is required). + */ + + FAR _TCB *wtcb = (FAR _TCB *)g_readytorun.head; + if (wtcb->sched_priority > CONFIG_PAGING_DEFPRIO && + wtcb->sched_priority > g_pftcb->sched_priority) + { + /* Don't reduce the priority of the page fill + * worker thread lower than the configured + * minimum. + */ + + int priority = g_pftcb->sched_priority; + if (priority < CONFIG_PAGING_DEFPRIO) + { + priority = CONFIG_PAGING_DEFPRIO; + } + + /* Reduce the priority of the page fill worker thread */ + + pgllvdbg("New worker priority. %d->%d\n", + wtcb->sched_priority, priority); + sched_setpriority(wtcb, priority); + } + + /* Return with g_pftcb holding the pointer to + * the TCB associated with task that requires the page fill. + */ + + return true; + } + + /* The page need by this task has already been mapped into the + * virtual address space -- just restart it. + */ + + pglldbg("Restarting TCB: %p\n", g_pftcb); + up_unblock_task(g_pftcb); + } + } + while (g_pftcb != NULL); + + return false; +} + +/**************************************************************************** + * Name: pg_startfill + * + * Description: + * Start a page fill operation on the thread whose TCB is at the head of + * of the g_waitingforfill task list. That is a prioritized list so that + * will be the highest priority task waiting for a page fill (in the event + * that are multiple tasks waiting for a page fill). + * + * This function may be called either (1) when the page fill worker thread + * is notified that there is a new page fill TCB in the g_waitingforfill + * prioritized list, or (2) when a page fill completes and there are more + * pages to be filled in g_waitingforfill list. + * + * Input parameters: + * None + * + * Returned Value: + * If there are no further queue page fill operations to be performed, + * pg_startfill() will return false. Otherwise, it will return + * true to that the full is in process (any errors will result in + * assertions and this function will not return). + * + * Assumptions: + * Executing in the context of the page fill worker thread with all + * interrupts disabled. + * + ****************************************************************************/ + +static inline bool pg_startfill(void) +{ + FAR void *vpage; + int result; + + /* Remove the TCB at the head of the g_waitfor fill list and check if there + * is any task waiting for a page fill. pg_dequeue will handle this (plus + * some cornercases) and will true if the next page TCB was successfully + * dequeued. + */ + + if (pg_dequeue()) + { + /* Call up_allocpage(tcb, &vpage). This architecture-specific function will + * set aside page in memory and map to virtual address (vpage). If all + * available pages are in-use (the typical case), this function will select + * a page in-use, un-map it, and make it available. + */ + + pgllvdbg("Call up_allocpage(%p)\n", g_pftcb); + result = up_allocpage(g_pftcb, &vpage); + DEBUGASSERT(result == OK); + + /* Start the fill. The exact way that the fill is started depends upon + * the nature of the architecture-specific up_fillpage() function -- Is it + * a blocking or a non-blocking call? + */ +#ifdef CONFIG_PAGING_BLOCKINGFILL + /* If CONFIG_PAGING_BLOCKINGFILL is defined, then up_fillpage is blocking + * call. In this case, up_fillpage() will accept only (1) a reference to + * the TCB that requires the fill. Architecture-specific context information + * within the TCB will be sufficient to perform the fill. And (2) the + * (virtual) address of the allocated page to be filled. The resulting + * status of the fill will be provided by return value from up_fillpage(). + */ + + pgllvdbg("Call up_fillpage(%p)\n", g_pftcb); + result = up_fillpage(g_pftcb, vpage); + DEBUGASSERT(result == OK); +#else + /* If CONFIG_PAGING_BLOCKINGFILL is defined, then up_fillpage is non-blocking + * call. In this case up_fillpage() will accept an additional argument: The page + * fill worker thread will provide a callback function, pg_callback. + * + * Calling up_fillpage will start an asynchronous page fill. pg_callback + * ill be called when the page fill is finished (or an error occurs). This + * This callback will probably from interrupt level. + */ + + pgllvdbg("Call up_fillpage(%p)\n", g_pftcb); + result = up_fillpage(g_pftcb, vpage, pg_callback); + DEBUGASSERT(result == OK); + + /* Save the time that the fill was started. These will be used to check for + * timeouts. + */ + +#ifdef CONFIG_PAGING_TIMEOUT_TICKS + g_starttime = clock_systimer(); +#endif + + /* Return and wait to be signaled for the next event -- the fill completion + * event. While the fill is in progress, other tasks may execute. If + * another page fault occurs during this time, the faulting task will be + * blocked, its TCB will be added (in priority order) to g_waitingforfill + * and the priority of the page worker task may be boosted. But no action + * will be taken until the current page fill completes. NOTE: The IDLE task + * must also be fully locked in memory. The IDLE task cannot be blocked. It + * the case where all tasks are blocked waiting for a page fill, the IDLE + * task must still be available to run. + */ +#endif /* CONFIG_PAGING_BLOCKINGFILL */ + + return true; + } + + pglldbg("Queue empty\n"); + return false; +} + +/**************************************************************************** + * Name: pg_alldone + * + * Description: + * Called by the page fill worker thread when all pending page fill + * operations have been completed and the g_waitingforfill list is empty. + * + * This functin will perform the following operations: + * + * - Set g_pftcb to NULL. + * - Restore the default priority of the page fill worker thread. + * + * Input parameters: + * None. + * + * Returned Value: + * None + * + * Assumptions: + * Executing in the context of the page fill worker thread with interrupts + * disabled. + * + ****************************************************************************/ + +static inline void pg_alldone(void) +{ + FAR _TCB *wtcb = (FAR _TCB *)g_readytorun.head; + g_pftcb = NULL; + pgllvdbg("New worker priority. %d->%d\n", + wtcb->sched_priority, CONFIG_PAGING_DEFPRIO); + sched_setpriority(wtcb, CONFIG_PAGING_DEFPRIO); +} + +/**************************************************************************** + * Name: pg_fillcomplete + * + * Description: + * Called by the page fill worker thread when a page fill completes. + * Either (1) in the non-blocking up_fillpage(), after the architecture- + * specific driver call the pg_callback() to wake up the page fill worker + * thread, or (2) after the blocking up_fillpage() returens (when + * CONFIG_PAGING_BLOCKINGFILL is defined). + * + * This function is just a dumb wrapper around up_unblocktask(). This + * function simply makes the task that just received the fill ready-to-run. + * + * Input parameters: + * None. + * + * Returned Value: + * None + * + * Assumptions: + * Executing in the context of the page fill worker thread with interrupts + * disabled. + * + ****************************************************************************/ + +static inline void pg_fillcomplete(void) +{ + /* Call up_unblocktask(g_pftcb) to make the task that just + * received the fill ready-to-run. + */ + + pglldbg("Restarting TCB: %p\n", g_pftcb); + up_unblock_task(g_pftcb); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ +/**************************************************************************** + * Name: pg_worker + * + * Description: + * This is the page fill worker thread that performs pages fills for tasks + * that have received a pag fault and are blocked in the g_waitingforfill + * task queue. + * + * The page fill worker thread will be awakened on one of three conditions: + * - When signaled by pg_miss(), the page fill worker thread will be + * awakenend, or + * - if CONFIG_PAGING_BLOCKINGFILL is not defined, from pg_callback() + * after completing a page fill. + * - A configurable timeout with no activity. + * + * Input parameters: + * argc, argv (not used) + * + * Returned Value: + * Does not return + * + ****************************************************************************/ + +int pg_worker(int argc, char *argv[]) +{ + irqstate_t flags; + + /* Loop forever -- Notice that interrupts will be disable at all times that + * this thread runs. That is so that we con't lose signals or have + * asynchronous page faults. + * + * All interrupt logic as well as all page fill worker thread logic must + * be locked in memory. Therefore, keeping interrupts disabled here + * should prevent any concurrent page faults. Any page faults or page + * fill completions should occur while this thread sleeps. + */ + + pglldbg("Started\n"); + flags = irqsave(); + for (;;) + { + /* Wait awhile. We will wait here until either the configurable timeout + * elapses or until we are awakened by a signal (which terminates the + * usleep with an EINTR error). Note that interrupts will be re-enabled + * while this task sleeps. + * + * The timeout is a failsafe that will handle any cases where a single + * is lost (that would really be a bug and shouldn't happen!) and also + * supports timeouts for case of non-blocking, asynchronous fills. + */ + + usleep(CONFIG_PAGING_WORKPERIOD); + + /* The page fill worker thread will be awakened on one of three conditions: + * + * - When signaled by pg_miss(), the page fill worker thread will be awakenend, + * - if CONFIG_PAGING_BLOCKINGFILL is not defined, from pg_callback() + * after completing a page fill, or + * - On a configurable timeout expires with no activity. + * + * Interrupts are still disabled. + */ + +#ifndef CONFIG_PAGING_BLOCKINGFILL + /* For the non-blocking up_fillpage(), the page fill worker thread will detect + * that the page fill is complete when it is awakened with g_pftcb non-NULL + * and fill completion status from pg_callback. + */ + + if (g_pftcb != NULL) + { + /* If it is a real page fill completion event, then the result of the page + * fill will be in g_fillresult and will not be equal to -EBUSY. + */ + + if (g_fillresult != -EBUSY) + { + /* Any value other than OK, brings the system down */ + + ASSERT(g_fillresult == OK); + + /* Handle the successful page fill complete event by restarting the + * task that was blocked waiting for this page fill. + */ + + pglldbg("Restarting TCB: %p\n", g_pftcb); + up_unblock_task(g_pftcb);; + + /* Yes .. Start the next asynchronous fill. Check the return + * value to see a fill was actually started (false means that + * no fill was started). + */ + + pgllvdbg("Calling pg_startfill\n"); + if (!pg_startfill()) + { + /* No fill was started. This can mean only that all queued + * page fill actions have and been completed and there is + * nothing more to do. + */ + + pgllvdbg("Call pg_alldone()\n"); + pg_alldone(); + } + } + + /* If a configurable timeout period expires with no page fill completion + * event, then declare a failure. + */ + +#ifdef CONFIG_PAGING_TIMEOUT_TICKS + else + { + lldbg("Timeout!\n"); + ASSERT(clock_systimer() - g_starttime < CONFIG_PAGING_TIMEOUT_TICKS); + } +#endif + } + + /* Otherwise, this might be a page fill initiation event. When + * awakened from pg_miss(), no fill will be in progress and + * g_pftcb will be NULL. + */ + + else + { + /* Are there tasks blocked and waiting for a fill? If so, + * pg_startfill() will start the asynchronous fill (and set + * g_pftcb). + */ + + pgllvdbg("Calling pg_startfill\n"); + (void)pg_startfill(); + } +#else + /* Are there tasks blocked and waiting for a fill? Loop until all + * pending fills have been processed. + */ + + for (;;) + { + /* Yes .. Start the fill and block until the fill completes. + * Check the return value to see a fill was actually performed. + * (false means that no fill was perforemd). + */ + + pgllvdbg("Calling pg_startfill\n"); + if (!pg_startfill()) + { + /* Break out of the loop -- there is nothing more to do */ + + break; + } + + /* Handle the page fill complete event by restarting the + * task that was blocked waiting for this page fill. In the + * non-blocking fill case, the page fill worker thread will + * know that the page fill is complete when pg_startfill() + * returns true. + */ + + pgllvdbg("Restarting TCB: %p\n", g_pftcb); + up_unblock_task(g_pftcb);; + } + + /* All queued fills have been processed */ + + pgllvdbg("Call pg_alldone()\n"); + pg_alldone(); +#endif + } + + return OK; /* To keep some compilers happy */ +} +#endif /* CONFIG_PAGING */ diff --git a/nuttx/sched/prctl.c b/nuttx/sched/prctl.c new file mode 100644 index 000000000..d71a0e174 --- /dev/null +++ b/nuttx/sched/prctl.c @@ -0,0 +1,167 @@ +/************************************************************************ + * sched/prctl.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include + +#include + +#include "os_internal.h" + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/**************************************************************************** + * Name: prctl + * + * Description: + * prctl() is called with a first argument describing what to do (with + * values PR_* defined above) and with additional arguments depending on + * the specific command. + * + * Returned Value: + * The returned value may depend on the specific commnand. For PR_SET_NAME + * and PR_GET_NAME, the returned value of 0 indicates successful operation. + * On any failure, -1 is retruend and the errno value is set appropriately. + * + * EINVAL The value of 'option' is not recognized. + * EFAULT optional arg1 is not a valid address. + * ESRCH No task/thread can be found corresponding to that specified + * by optional arg1. + * + ****************************************************************************/ + +int prctl(int option, ...) +{ + va_list ap; + int err; + + va_start(ap, option); + switch (option) + { + case PR_SET_NAME: + case PR_GET_NAME: +#if CONFIG_TASK_NAME_SIZE > 0 + { + /* Get the prctl arguments */ + + FAR char *name = va_arg(ap, FAR char *); + int pid = va_arg(ap, int); + FAR _TCB *tcb; + + /* Get the TCB associated with the PID (handling the special case of + * pid==0 meaning "this thread") + */ + + if (!pid) + { + tcb = (FAR _TCB *)g_readytorun.head; + } + else + { + tcb = sched_gettcb(pid); + } + + /* An invalid pid will be indicated by a NULL TCB returned from + * sched_gettcb() + */ + + if (!tcb) + { + sdbg("Pid does not correspond to a task: %d\n", pid); + err = ESRCH; + goto errout; + } + + /* A pointer to the task name storage must also be provided */ + + if (!name) + { + sdbg("No name provide\n"); + err = EFAULT; + goto errout; + } + + /* Now get or set the task name */ + + if (option == PR_SET_NAME) + { + /* tcb->name may not be null-terminated */ + + strncpy(tcb->name, name, CONFIG_TASK_NAME_SIZE); + } + else + { + /* The returned value will be null-terminated, truncating if necessary */ + + strncpy(name, tcb->name, CONFIG_TASK_NAME_SIZE-1); + name[CONFIG_TASK_NAME_SIZE-1] = '\0'; + } + } + break; +#else + sdbg("Option not enabled: %d\n", option); + err = ENOSYS; + goto errout; +#endif + + default: + sdbg("Unrecognized option: %d\n", option); + err = EINVAL; + goto errout; + } + + va_end(ap); + return OK; + +errout: + va_end(ap); + set_errno(err); + return ERROR; +} diff --git a/nuttx/sched/pthread_barrierdestroy.c b/nuttx/sched/pthread_barrierdestroy.c new file mode 100644 index 000000000..40e8e875c --- /dev/null +++ b/nuttx/sched/pthread_barrierdestroy.c @@ -0,0 +1,110 @@ +/******************************************************************************** + * sched/pthread_barriedestroy.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include + +/******************************************************************************** + * Definitions + ********************************************************************************/ + +/******************************************************************************** + * Private Type Declarations + ********************************************************************************/ + +/******************************************************************************** + * Global Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Function Prototypes + ********************************************************************************/ + +/******************************************************************************** + * Public Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: pthread_barrier_destroy + * + * Description: + * The pthread_barrier_destroy() function destroys the barrier referenced by + * 'barrier' and releases any resources used by the barrier. The effect of + * subsequent use of the barrier is undefined until the barrier is + * reinitialized by another call to pthread_barrier_init(). The results are + * undefined if pthread_barrier_destroy() is called when any thread is blocked + * on the barrier, or if this function is called with an uninitialized barrier. + * + * Parameters: + * barrier - barrier to be destroyed. + * + * Return Value: + * 0 (OK) on success or on of the following error numbers: + * + * EBUSY The implementation has detected an attempt to destroy a barrier while + * it is in use. + * EINVAL The value specified by barrier is invalid. + * + * Assumptions: + * + ********************************************************************************/ + +int pthread_barrier_destroy(FAR pthread_barrier_t *barrier) +{ + int ret = OK; + + if (!barrier) + { + ret = EINVAL; + } + else + { + sem_destroy(&barrier->sem); + barrier->count = 0; + } + return ret; +} diff --git a/nuttx/sched/pthread_barrierinit.c b/nuttx/sched/pthread_barrierinit.c new file mode 100644 index 000000000..73b974b18 --- /dev/null +++ b/nuttx/sched/pthread_barrierinit.c @@ -0,0 +1,122 @@ +/******************************************************************************** + * sched/pthread_barrieinit.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include + +/******************************************************************************** + * Definitions + ********************************************************************************/ + +/******************************************************************************** + * Private Type Declarations + ********************************************************************************/ + +/******************************************************************************** + * Global Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Function Prototypes + ********************************************************************************/ + +/******************************************************************************** + * Public Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: pthread_barrier_init + * + * Description: + * The pthread_barrier_init() function allocates any resources required to use + * the barrier referenced by 'barrier' and initialized the barrier with the + * attributes referenced by attr. If attr is NULL, the default barrier + * attributes will be used. The results are undefined if pthread_barrier_init() + * is called when any thread is blocked on the barrier. The results are + * undefined if a barrier is used without first being initialized. The results + * are undefined if pthread_barrier_init() is called specifying an already + * initialized barrier. + * + * Parameters: + * barrier - the barrier to be initialized + * attr - barrier attributes to be used in the initialization. + * count - the count to be associated with the barrier. The count argument + * specifies the number of threads that must call pthread_barrier_wait() before + * any of them successfully return from the call. The value specified by + * count must be greater than zero. + * + * Return Value: + * 0 (OK) on success or on of the following error numbers: + * + * EAGAIN The system lacks the necessary resources to initialize another barrier. + * EINVAL The barrier reference is invalid, or the values specified by attr are + * invalid, or the value specified by count is equal to zero. + * ENOMEM Insufficient memory exists to initialize the barrier. + * EBUSY The implementation has detected an attempt to reinitialize a barrier + * while it is in use. + * + * Assumptions: + * + ********************************************************************************/ + +int pthread_barrier_init(FAR pthread_barrier_t *barrier, + FAR const pthread_barrierattr_t *attr, unsigned int count) +{ + int ret = OK; + + if (!barrier || count == 0) + { + ret = EINVAL; + } + else + { + sem_init(&barrier->sem, 0, 0); + barrier->count = count; + } + + return ret; +} diff --git a/nuttx/sched/pthread_barrierwait.c b/nuttx/sched/pthread_barrierwait.c new file mode 100644 index 000000000..8ca8d1754 --- /dev/null +++ b/nuttx/sched/pthread_barrierwait.c @@ -0,0 +1,182 @@ +/******************************************************************************** + * sched/pthread_barrierwait.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include + +/******************************************************************************** + * Definitions + ********************************************************************************/ + +/******************************************************************************** + * Private Type Declarations + ********************************************************************************/ + +/******************************************************************************** + * Global Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Function Prototypes + ********************************************************************************/ + +/******************************************************************************** + * Public Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: pthread_barrier_wait + * + * Description: + * The pthread_barrier_wait() function synchronizse participating threads at + * the barrier referenced by 'barrier'. The calling thread is blocked until + * the required number of threads have called pthread_barrier_wait() specifying + * the same 'barrier'. When the required number of threads have called + * pthread_barrier_wait() specifying the 'barrier', the constant + * PTHREAD_BARRIER_SERIAL_THREAD will be returned to one unspecified thread + * and zero will be returned to each of the remaining threads. At this point, + * the barrier will be reset to the state it had as a result of the most recent + * pthread_barrier_init() function that referenced it. + * + * The constant PTHREAD_BARRIER_SERIAL_THREAD is defined in pthread.h and its + * value must be distinct from any other value returned by pthread_barrier_wait(). + * + * The results are undefined if this function is called with an uninitialized + * barrier. + * + * If a signal is delivered to a thread blocked on a barrier, upon return from + * the signal handler the thread will resume waiting at the barrier if the barrier + * wait has not completed; otherwise, the thread will continue as normal from + * the completed barrier wait. Until the thread in the signal handler returns + * from it, it is unspecified whether other threads may proceed past the barrier + * once they have all reached it. + * + * A thread that has blocked on a barrier will not prevent any unblocked thread + * that is eligible to use the same processing resources from eventually making + * forward progress in its execution. Eligibility for processing resources will + * be determined by the scheduling policy. + * + * Parameters: + * barrier - the barrier to wait on + * + * Return Value: + * 0 (OK) on success or EINVAL if the barrier is not valid. + * + * Assumptions: + * + ********************************************************************************/ + +int pthread_barrier_wait(FAR pthread_barrier_t *barrier) +{ + int semcount; + int ret = OK; + + if (!barrier) + { + return EINVAL; + } + + /* Disable pre-emption throughout the following */ + + sched_lock(); + + /* Find out how many threads are already waiting at the barrier */ + + ret = sem_getvalue(&barrier->sem, &semcount); + if (ret != OK) + { + sched_unlock(); + return EINVAL; + } + + /* If the number of waiters would be equal to the count, then we are done */ + + if (1 - semcount >= barrier->count) + { + /* Free all of the waiting threads */ + + while (semcount < 0) + { + (void)sem_post(&barrier->sem); + (void)sem_getvalue(&barrier->sem, &semcount); + } + + /* Then return PTHREAD_BARRIER_SERIAL_THREAD to the final thread */ + + sched_unlock(); + return PTHREAD_BARRIER_SERIAL_THREAD; + } + else + { + /* Otherwise, this thread must wait as well */ + + while (sem_wait(&barrier->sem) != OK) + { + /* If the thread is awakened by a signal, just continue to wait */ + + int errornumber = get_errno(); + if (errornumber != EINTR) + { + /* If it is awakened by some other error, then there is a + * problem + */ + + sched_unlock(); + return errornumber; + } + } + + /* We will only get here when we are one of the N-1 threads that were + * waiting for the final thread at the barrier. We just need to return + * zero. + */ + + sched_unlock(); + return 0; + } +} diff --git a/nuttx/sched/pthread_cancel.c b/nuttx/sched/pthread_cancel.c new file mode 100644 index 000000000..5e34eeaba --- /dev/null +++ b/nuttx/sched/pthread_cancel.c @@ -0,0 +1,148 @@ +/************************************************************************** + * sched/pthread_cancel.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include + +#include "os_internal.h" +#include "pthread_internal.h" + +/************************************************************************** + * Private Definitions + **************************************************************************/ + +/************************************************************************** + * Private Types + **************************************************************************/ + +/************************************************************************** + * Private Function Prototypes + **************************************************************************/ + +/************************************************************************** + * Global Variables + **************************************************************************/ + +/************************************************************************** + * Private Variables + **************************************************************************/ + +/************************************************************************** + * Private Functions + **************************************************************************/ + +/************************************************************************** + * Public Functions + **************************************************************************/ + +int pthread_cancel(pthread_t thread) +{ + _TCB *tcb; + + /* First, make sure that the handle references a valid thread */ + + if (!thread) + { + /* pid == 0 is the IDLE task. Callers cannot cancel the + * IDLE task. + */ + + return ESRCH; + } + + tcb = sched_gettcb((pid_t)thread); + if (!tcb) + { + /* The pid does not correspond to any known thread */ + + return ESRCH; + } + + /* Check to see if this thread has the non-cancelable bit set in its + * flags. Suppress context changes for a bit so that the flags are stable. + * (the flags should not change in interrupt handling. + */ + + sched_lock(); + if ((tcb->flags & TCB_FLAG_NONCANCELABLE) != 0) + { + /* Then we cannot cancel the thread now. Here is how this is + * supposed to work: + * + * "When cancelability is disabled, all cancels are held pending + * in the target thread until the thread changes the cancelability. + * When cancelability is deferred, all cancels are held pending in + * the target thread until the thread changes the cancelability, calls + * a function which is a cancellation point or calls pthread_testcancel(), + * thus creating a cancellation point. When cancelability is asynchronous, + * all cancels are acted upon immediately, interrupting the thread with its + * processing." + */ + + tcb->flags |= TCB_FLAG_CANCEL_PENDING; + sched_unlock(); + return OK; + } + + sched_unlock(); + + /* Check to see if the ID refers to ourselves.. this would be the + * same as pthread_exit(PTHREAD_CANCELED). + */ + + if (tcb == (_TCB*)g_readytorun.head) + { + pthread_exit(PTHREAD_CANCELED); + } + + /* Complete pending join operations */ + + (void)pthread_completejoin((pid_t)thread, PTHREAD_CANCELED); + + /* Then let pthread_delete do the real work */ + + task_delete((pid_t)thread); + return OK; +} + + diff --git a/nuttx/sched/pthread_completejoin.c b/nuttx/sched/pthread_completejoin.c new file mode 100644 index 000000000..7c5191034 --- /dev/null +++ b/nuttx/sched/pthread_completejoin.c @@ -0,0 +1,231 @@ +/************************************************************************ + * sched/pthread_completejoin.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include + +#include "os_internal.h" +#include "pthread_internal.h" + +/************************************************************************ + * Pre-processor Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Name: pthread_notifywaiters + * + * Description: + * Notify all other threads waiting in phread join for this thread's + * exit data. This must be done by the child at child thread + * destruction time. + * + ************************************************************************/ + +static bool pthread_notifywaiters(FAR join_t *pjoin) +{ + int ntasks_waiting; + int status; + + svdbg("pjoin=0x%p\n", pjoin); + + /* Are any tasks waiting for our exit value? */ + + status = sem_getvalue(&pjoin->exit_sem, &ntasks_waiting); + if (status == OK && ntasks_waiting < 0) + { + /* Set the data semaphore so that this thread will be + * awakened when all waiting tasks receive the data + */ + + (void)sem_init(&pjoin->data_sem, 0, (ntasks_waiting+1)); + + /* Post the semaphore to restart each thread that is waiting + * on the semaphore + */ + + do + { + status = pthread_givesemaphore(&pjoin->exit_sem); + if (status == OK) + { + status = sem_getvalue(&pjoin->exit_sem, &ntasks_waiting); + } + } + while (ntasks_waiting < 0 && status == OK); + + /* Now wait for all these restarted tasks to obtain the return + * value. + */ + + (void)pthread_takesemaphore(&pjoin->data_sem); + return true; + } + + return false; +} + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: pthread_completejoin + * + * Description: + * A thread has been terminated -- either by returning, calling + * pthread_exit(), or through pthread_cancel(). In any event, we must + * complete any pending join events. + * + * Parameters: + * exit_value + * + * Returned Value: + * OK unless there is no join information associated with the pid. + * This could happen, for example, if a task started with task_create() + * calls pthread_exit(). + * + * Assumptions: + * + ************************************************************************/ + +int pthread_completejoin(pid_t pid, FAR void *exit_value) +{ + FAR join_t *pjoin; + + svdbg("pid=%d exit_value=%p\n", pid, exit_value); + + /* First, find thread's structure in the private data set. */ + + (void)pthread_takesemaphore(&g_join_semaphore); + pjoin = pthread_findjoininfo(pid); + if (!pjoin) + { + sdbg("Could not find join info, pid=%d\n", pid); + (void)pthread_givesemaphore(&g_join_semaphore); + return ERROR; + } + else + { + bool waiters; + + /* Save the return exit value in the thread structure. */ + + pjoin->terminated = true; + pjoin->exit_value = exit_value; + + /* Notify waiters of the availability of the exit value */ + + waiters = pthread_notifywaiters(pjoin); + + /* If there are no waiters and if the thread is marked as detached. + * then discard the join information now. Otherwise, the pthread + * join logic will call pthread_destroyjoin() when all of the threads + * have sampled the exit value. + */ + + if (!waiters && pjoin->detached) + { + pthread_destroyjoin(pjoin); + } + + /* Giving the following semaphore will allow the waiters + * to call pthread_destroyjoin. + */ + + (void)pthread_givesemaphore(&g_join_semaphore); + } + + return OK; +} + +/************************************************************************ + * Name: pthread_destroyjoin + * + * Description: + * This is called from pthread_completejoin if the join info was + * detached or from pthread_join when the last waiting thread has + * received the thread exit info. + * + * Or it may never be called if the join info was never detached or if + * no thread ever calls pthread_join. In case, there is a memory leak! + * + * Assumptions: + * The caller holds g_join_semaphore + * + ************************************************************************/ + +void pthread_destroyjoin(FAR join_t *pjoin) +{ + sdbg("pjoin=0x%p\n", pjoin); + + /* Remove the join info from the set of joins */ + + (void)pthread_removejoininfo((pid_t)pjoin->thread); + + /* Destroy its semaphores */ + + (void)sem_destroy(&pjoin->data_sem); + (void)sem_destroy(&pjoin->exit_sem); + + /* And deallocate the pjoin structure */ + + sched_free(pjoin); +} + diff --git a/nuttx/sched/pthread_condbroadcast.c b/nuttx/sched/pthread_condbroadcast.c new file mode 100644 index 000000000..05f4bb483 --- /dev/null +++ b/nuttx/sched/pthread_condbroadcast.c @@ -0,0 +1,145 @@ +/**************************************************************************** + * sched/pthread_condbroadcast.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include + +#include "pthread_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_cond_broadcast + * + * Description: + * A thread broadcast on a condition variable. + * + * Parameters: + * None + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_cond_broadcast(FAR pthread_cond_t *cond) +{ + int ret = OK; + int sval; + + sdbg("cond=0x%p\n", cond); + + if (!cond) + { + ret = EINVAL; + } + else + { + /* Disable pre-emption until all of the waiting threads have been + * restarted. This is necessary to assure that the sval behaves as + * expected in the following while loop + */ + + sched_lock(); + + /* Get the current value of the semaphore */ + + if (sem_getvalue((sem_t*)&cond->sem, &sval) != OK) + { + ret = EINVAL; + } + else + { + /* Loop until all of the waiting threads have been restarted. */ + + while (sval < 0) + { + /* If the value is less than zero (meaning that one or more + * thread is waiting), then post the condition semaphore. + * Only the highest priority waiting thread will get to execute + */ + + ret = pthread_givesemaphore((sem_t*)&cond->sem); + + /* Increment the semaphore count (as was done by the + * above post). + */ + + sval++; + } + } + + /* Now we can let the restarted threads run */ + + sched_unlock(); + } + + sdbg("Returning %d\n", ret); + return ret; +} + + diff --git a/nuttx/sched/pthread_conddestroy.c b/nuttx/sched/pthread_conddestroy.c new file mode 100644 index 000000000..11292e639 --- /dev/null +++ b/nuttx/sched/pthread_conddestroy.c @@ -0,0 +1,88 @@ +/**************************************************************************** + * sched/pthread_conddestroy.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include "pthread_internal.h" + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_cond_destroy + * + * Description: + * A thread can delete condition variables. + * + * Parameters: + * None + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_cond_destroy(FAR pthread_cond_t *cond) +{ + int ret = OK; + + sdbg("cond=0x%p\n", cond); + + if (!cond) + { + ret = EINVAL; + } + + /* Destroy the semaphore contained in the structure */ + + else if (sem_destroy((sem_t*)&cond->sem) != OK) + { + ret = EINVAL; + } + + sdbg("Returning %d\n", ret); + return ret; +} + diff --git a/nuttx/sched/pthread_condinit.c b/nuttx/sched/pthread_condinit.c new file mode 100644 index 000000000..e49bb8658 --- /dev/null +++ b/nuttx/sched/pthread_condinit.c @@ -0,0 +1,93 @@ +/**************************************************************************** + * sched/pthread_condinit.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include + +#include "pthread_internal.h" + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_cond_init + * + * Description: + * A thread can create condition variables. + * + * Parameters: + * None + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_cond_init(FAR pthread_cond_t *cond, FAR pthread_condattr_t *attr) +{ + int ret = OK; + + sdbg("cond=0x%p attr=0x%p\n", cond, attr); + + if (!cond) + { + ret = EINVAL; + } + + /* Initialize the semaphore contained in the condition structure + * with initial count = 0 + */ + + else if (sem_init((sem_t*)&cond->sem, 0, 0) != OK) + { + ret = EINVAL; + } + + sdbg("Returning %d\n", ret); + return ret; +} + + + diff --git a/nuttx/sched/pthread_condsignal.c b/nuttx/sched/pthread_condsignal.c new file mode 100644 index 000000000..48ff4cf20 --- /dev/null +++ b/nuttx/sched/pthread_condsignal.c @@ -0,0 +1,137 @@ +/**************************************************************************** + * sched/pthread_condsignal.c + * + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include + +#include "pthread_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_cond_signal + * + * Description: + * A thread can signal on a condition variable. + * + * Parameters: + * None + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_cond_signal(FAR pthread_cond_t *cond) +{ + int ret = OK; + int sval; + + sdbg("cond=0x%p\n", cond); + + if (!cond) + { + ret = EINVAL; + } + else + { + /* Get the current value of the semaphore */ + + if (sem_getvalue((sem_t*)&cond->sem, &sval) != OK) + { + ret = EINVAL; + } + + /* If the value is less than zero (meaning that one or more + * thread is waiting), then post the condition semaphore. + * Only the highest priority waiting thread will get to execute + */ + + else + { + /* One of my objectives in this design was to make pthread_cond_signal + * usable from interrupt handlers. However, from interrupt handlers, + * you cannot take the associated mutex before signaling the condition. + * As a result, I think that there could be a race condition with + * the following logic which assumes that the if sval < 0 then the + * thread is waiting. Without the mutex, there is no atomic, protected + * operation that will guarantee this to be so. + */ + + sdbg("sval=%d\n", sval); + if (sval < 0) + { + sdbg("Signalling...\n"); + ret = pthread_givesemaphore((sem_t*)&cond->sem); + } + } + } + + sdbg("Returning %d\n", ret); + return ret; +} + + diff --git a/nuttx/sched/pthread_condtimedwait.c b/nuttx/sched/pthread_condtimedwait.c new file mode 100644 index 000000000..25f86d813 --- /dev/null +++ b/nuttx/sched/pthread_condtimedwait.c @@ -0,0 +1,308 @@ +/**************************************************************************** + * sched/pthread_condtimedwait.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "os_internal.h" +#include "pthread_internal.h" +#include "clock_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_condtimedout + * + * Description: + * This function is called if the timeout elapses before + * the condition is signaled. + * + * Parameters: + * argc - the number of arguments (should be 2) + * pid - the task ID of the task to wakeup + * signo - The signal to use to wake up the task + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void pthread_condtimedout(int argc, uint32_t pid, uint32_t signo) +{ +#ifdef CONFIG_CAN_PASS_STRUCTS + union sigval value; + + /* Send the specified signal to the specified task. */ + + value.sival_ptr = NULL; + (void)sigqueue((int)pid, (int)signo, value); +#else + (void)sigqueue((int)pid, (int)signo, NULL); +#endif +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_cond_timedwait + * + * Description: + * A thread can perform a timed wait on a condition variable. + * + * Parameters: + * cond - the condition variable to wait on + * mutex - the mutex that protects the condition variable + * abstime - wait until this absolute time + * + * Return Value: + * OK (0) on success; ERROR (-1) on failure with errno + * set appropriately. + * + * Assumptions: + * Timing is of resolution 1 msec, with +/-1 millisecond + * accuracy. + * + ****************************************************************************/ + +int pthread_cond_timedwait(FAR pthread_cond_t *cond, FAR pthread_mutex_t *mutex, + FAR const struct timespec *abstime) +{ + WDOG_ID wdog; + 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); + + /* 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 */ + + wdog = wd_create(); + if (!wdog) + { + 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(wdog, 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(wdog); + } + } + + sdbg("Returning %d\n", ret); + return ret; +} + diff --git a/nuttx/sched/pthread_condwait.c b/nuttx/sched/pthread_condwait.c new file mode 100644 index 000000000..bf0164d2d --- /dev/null +++ b/nuttx/sched/pthread_condwait.c @@ -0,0 +1,137 @@ +/**************************************************************************** + * sched/pthread_condwait.c + * + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include + +#include "pthread_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: int pthread_cond_wait + * + * Description: + * A thread can wait for a condition variable to be signalled or broadcast. + * + * Parameters: + * None + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_cond_wait(FAR pthread_cond_t *cond, FAR pthread_mutex_t *mutex) +{ + int ret; + + sdbg("cond=0x%p mutex=0x%p\n", cond, mutex); + + /* 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 != (int)getpid()) + { + ret = EPERM; + } + else + { + /* Give up the mutex */ + + sdbg("Give up mutex / take cond\n"); + + sched_lock(); + mutex->pid = 0; + ret = pthread_givesemaphore((sem_t*)&mutex->sem); + + /* Take the semaphore */ + + ret |= pthread_takesemaphore((sem_t*)&cond->sem); + sched_unlock(); + + /* Reacquire the mutex */ + + sdbg("Reacquire mutex...\n"); + ret |= pthread_takesemaphore((sem_t*)&mutex->sem); + if (!ret) + { + mutex->pid = getpid();; + } + } + + sdbg("Returning %d\n", ret); + return ret; +} + diff --git a/nuttx/sched/pthread_create.c b/nuttx/sched/pthread_create.c new file mode 100644 index 000000000..5fdf3b88d --- /dev/null +++ b/nuttx/sched/pthread_create.c @@ -0,0 +1,435 @@ +/**************************************************************************** + * sched/pthread_create.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "os_internal.h" +#include "clock_internal.h" +#include "env_internal.h" +#include "pthread_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/* Default pthread attributes */ + +pthread_attr_t g_default_pthread_attr = PTHREAD_ATTR_INITIALIZER; + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/* This is the name for name-less pthreads */ + +static const char g_pthreadname[] = ""; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_argsetup + * + * Description: + * This functions sets up parameters in the Task Control Block (TCB) in + * preparation for starting a new thread. + * + * pthread_argsetup() is called from task_init() and task_start() to create + * a new task (with arguments cloned via strdup) or pthread_create() which + * has one argument passed by value (distinguished by the pthread boolean + * argument). + * + * Input Parameters: + * tcb - Address of the new task's TCB + * name - Name of the new task (not used) + * argv - A pointer to an array of input parameters. Up to + * CONFIG_MAX_TASK_ARG parameters may be provided. If fewer + * than CONFIG_MAX_TASK_ARG parameters are passed, the list + * should be terminated with a NULL argv[] value. If no + * parameters are required, argv may be NULL. + * + * Return Value: + * None + * + ****************************************************************************/ + +static void pthread_argsetup(FAR _TCB *tcb, pthread_addr_t arg) +{ + int i; + +#if CONFIG_TASK_NAME_SIZE > 0 + /* Copy the pthread name into the TCB */ + + strncpy(tcb->name, g_pthreadname, CONFIG_TASK_NAME_SIZE); + + /* Save the name as the first argument in the TCB */ + + tcb->argv[0] = tcb->name; +#else + /* Save the name as the first argument in the TCB */ + + tcb->argv[0] = (char *)g_pthreadname; +#endif /* CONFIG_TASK_NAME_SIZE */ + + /* For pthreads, args are strictly pass-by-value; that actual + * type wrapped by pthread_addr_t is unknown. + */ + + tcb->argv[1] = (char*)arg; + + /* Nullify the remaining, unused argument storage */ + + for (i = 2; i < CONFIG_MAX_TASK_ARGS+1; i++) + { + tcb->argv[i] = NULL; + } +} + +/**************************************************************************** + * Name: pthread_addjoininfo + * + * Description: + * Add a join_t to the local data set. + * + * Parameters: + * pjoin + * + * Return Value: + * None + * + * Assumptions: + * The caller has provided protection from re-entrancy. + * + ****************************************************************************/ + +static void pthread_addjoininfo(FAR join_t *pjoin) +{ + pjoin->next = NULL; + if (!g_pthread_tail) + { + g_pthread_head = pjoin; + } + else + { + g_pthread_tail->next = pjoin; + } + + g_pthread_tail = pjoin; +} + +/**************************************************************************** + * Name: pthread_start + * + * Description: + * This function is the low level entry point into the + * pthread + * + * Parameters: + * None + * + ****************************************************************************/ + +static void pthread_start(void) +{ + FAR _TCB *ptcb = (FAR _TCB*)g_readytorun.head; + FAR join_t *pjoin = (FAR join_t*)ptcb->joininfo; + pthread_addr_t exit_status; + + /* Sucessfully spawned, add the pjoin to our data set. + * Don't re-enable pre-emption until this is done. + */ + + (void)pthread_takesemaphore(&g_join_semaphore); + pthread_addjoininfo(pjoin); + (void)pthread_givesemaphore(&g_join_semaphore); + + /* Report to the spawner that we successfully started. */ + + pjoin->started = true; + (void)pthread_givesemaphore(&pjoin->data_sem); + + /* Pass control to the thread entry point. The argument is + * argv[1]. argv[0] (the thread name) and argv[2-4] are not made + * available to the pthread. + */ + + exit_status = (*ptcb->entry.pthread)((pthread_addr_t)ptcb->argv[1]); + + /* The thread has returned */ + + pthread_exit(exit_status); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_create + * + * Description: + * This function creates and activates a new thread with a specified + * attributes. + * + * Input Parameters: + * thread + * attr + * start_routine + * arg + * + * Returned value: + * OK (0) on success; a (non-negated) errno value on failure. The errno + * variable is not set. + * + ****************************************************************************/ + +int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr, + pthread_startroutine_t start_routine, pthread_addr_t arg) +{ + FAR _TCB *ptcb; + FAR join_t *pjoin; + int status; + int priority; +#if CONFIG_RR_INTERVAL > 0 + int policy; +#endif + pid_t pid; + + /* 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 _TCB*)kzalloc(sizeof(_TCB)); + if (!ptcb) + { + return ENOMEM; + } + + /* Associate file descriptors with the new task */ + + status = sched_setuppthreadfiles(ptcb); + if (status != OK) + { + sched_releasetcb(ptcb); + return status; + } + + /* Share the parent's envionment */ + + (void)env_share(ptcb); + + /* Allocate a detachable structure to support pthread_join logic */ + + pjoin = (FAR join_t*)kzalloc(sizeof(join_t)); + if (!pjoin) + { + sched_releasetcb(ptcb); + return ENOMEM; + } + + /* Allocate the stack for the TCB */ + + status = up_create_stack(ptcb, attr->stacksize); + if (status != OK) + { + sched_releasetcb(ptcb); + sched_free(pjoin); + return ENOMEM; + } + + /* 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 for this thread. */ + + struct sched_param param; + status = sched_getparam(0, ¶m); + if (status == OK) + { + priority = param.sched_priority; + } + else + { + priority = SCHED_FIFO; + } + + /* Get the scheduler policy for this thread */ + +#if CONFIG_RR_INTERVAL > 0 + policy = sched_getscheduler(0); + if (policy == ERROR) + { + policy = SCHED_FIFO; + } +#endif + } + else + { + /* Use the priority and scheduler from the attributes */ + + priority = attr->priority; +#if CONFIG_RR_INTERVAL > 0 + policy = attr->policy; +#endif + } + + /* Mark this task as a pthread (this setting will be needed in + * task_schedsetup() when up_initial_state() is called. + */ + + ptcb->flags |= TCB_FLAG_TTYPE_PTHREAD; + + /* Initialize the task control block */ + + status = task_schedsetup(ptcb, priority, pthread_start, + (main_t)start_routine); + if (status != OK) + { + + sched_releasetcb(ptcb); + sched_free(pjoin); + return EBUSY; + } + + /* Configure the TCB for a pthread receiving on parameter + * passed by value + */ + + pthread_argsetup(ptcb, arg); + + /* Attach the join info to the TCB. */ + + ptcb->joininfo = (void*)pjoin; + + /* If round robin scheduling is selected, set the appropriate flag + * in the TCB. + */ + +#if CONFIG_RR_INTERVAL > 0 + if (policy == SCHED_RR) + { + ptcb->flags |= TCB_FLAG_ROUND_ROBIN; + ptcb->timeslice = CONFIG_RR_INTERVAL / MSEC_PER_TICK; + } +#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->pid; + pjoin->thread = (pthread_t)pid; + + /* Initialize the semaphores in the join structure to zero. */ + + status = sem_init(&pjoin->data_sem, 0, 0); + if (status == OK) + { + status = sem_init(&pjoin->exit_sem, 0, 0); + } + + /* Activate the task */ + + sched_lock(); + if (status == OK) + { + status = task_activate(ptcb); + } + + if (status == OK) + { + /* Wait for the task to actually get running and to register + * its join_t + */ + + (void)pthread_takesemaphore(&pjoin->data_sem); + + /* Return the thread information to the caller */ + + if (thread) *thread = (pthread_t)pid; + if (!pjoin->started) status = ERROR; + + sched_unlock(); + (void)sem_destroy(&pjoin->data_sem); + } + else + { + sched_unlock(); + dq_rem((FAR dq_entry_t*)ptcb, (dq_queue_t*)&g_inactivetasks); + (void)sem_destroy(&pjoin->data_sem); + (void)sem_destroy(&pjoin->exit_sem); + sched_releasetcb(ptcb); + sched_free(pjoin); + return EIO; + } + + return OK; +} diff --git a/nuttx/sched/pthread_detach.c b/nuttx/sched/pthread_detach.c new file mode 100644 index 000000000..a959d94b3 --- /dev/null +++ b/nuttx/sched/pthread_detach.c @@ -0,0 +1,137 @@ +/************************************************************************ + * sched/pthread_detach.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include + +#include "os_internal.h" +#include "pthread_internal.h" + +/************************************************************************ + * Pre-processor Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: pthread_detach + * + * Description: + * A thread object may be "detached" to specify that the return value + * and completion status will not be requested. + * + * Parameters: + * thread + * + * Return Value: + * 0 if successful. Otherwise, an error code. + * + * Assumptions: + * + ************************************************************************/ + +int pthread_detach(pthread_t thread) +{ + FAR join_t *pjoin; + int ret; + + sdbg("Thread=%d\n", thread); + + /* Find the entry associated with this pthread. */ + + (void)pthread_takesemaphore(&g_join_semaphore); + pjoin = pthread_findjoininfo((pid_t)thread); + if (!pjoin) + { + sdbg("Could not find thread entry\n"); + ret = EINVAL; + } + else + { + /* Has the thread already terminated? */ + + if (pjoin->terminated) + { + /* YES.. just remove the thread entry. */ + + pthread_destroyjoin(pjoin); + } + else + { + /* NO.. Just mark the thread as detached. It + * will be removed and deallocated when the + * thread exits + */ + + pjoin->detached = true; + } + + /* Either case is successful */ + + ret = OK; + } + + (void)pthread_givesemaphore(&g_join_semaphore); + + sdbg("Returning %d\n", ret); + return ret; +} diff --git a/nuttx/sched/pthread_exit.c b/nuttx/sched/pthread_exit.c new file mode 100644 index 000000000..db51be78f --- /dev/null +++ b/nuttx/sched/pthread_exit.c @@ -0,0 +1,137 @@ +/************************************************************************ + * sched/pthread_exit.c + * + * Copyright (C) 2007, 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "pthread_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: pthread_exit + * + * Description: + * Terminate execution of a thread started with pthread_create. + * + * Parameters: + * exit_valie + * + * Returned Value: + * None + * + * Assumptions: + * + ************************************************************************/ + +void pthread_exit(FAR void *exit_value) +{ + int error_code = (int)((intptr_t)exit_value); + int status; + + sdbg("exit_value=%p\n", exit_value); + + /* Block any signal actions that would awaken us while were + * are performing the JOIN handshake. + */ + +#ifndef CONFIG_DISABLE_SIGNALS + { + sigset_t set = ALL_SIGNAL_SET; + (void)sigprocmask(SIG_SETMASK, &set, NULL); + } +#endif + + /* Complete pending join operations */ + + status = pthread_completejoin(getpid(), exit_value); + if (status != OK) + { + /* Assume that the join completion failured because this + * not really a pthread. Exit by calling exit() to flush + * and close all file descriptors and calling atexit() + * functions. + */ + + if (error_code == EXIT_SUCCESS) + { + error_code = EXIT_FAILURE; + } + + exit(error_code); + } + + /* Then just exit, retaining all file descriptors and without + * calling atexit() functions. + */ + + _exit(error_code); +} + diff --git a/nuttx/sched/pthread_findjoininfo.c b/nuttx/sched/pthread_findjoininfo.c new file mode 100644 index 000000000..584ed8f96 --- /dev/null +++ b/nuttx/sched/pthread_findjoininfo.c @@ -0,0 +1,101 @@ +/************************************************************************ + * pthread_findjoininfo.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include + +#include "pthread_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: thread_findjoininfo + * + * Description: + * Find a join_t to the local data set. + * + * Parameters: + * pid + * + * Return Value: + * None or pointer to the found entry. + * + * Assumptions: + * The caller has provided protection from re-entrancy. + * + ************************************************************************/ + +FAR join_t *pthread_findjoininfo(pid_t pid) +{ + FAR join_t *pjoin; + + /* Find the entry with the matching pid */ + + for (pjoin = g_pthread_head; + (pjoin && (pid_t)pjoin->thread != pid); + pjoin = pjoin->next); + + /* and return it */ + + return pjoin; +} + diff --git a/nuttx/sched/pthread_getschedparam.c b/nuttx/sched/pthread_getschedparam.c new file mode 100644 index 000000000..c376fd400 --- /dev/null +++ b/nuttx/sched/pthread_getschedparam.c @@ -0,0 +1,139 @@ +/**************************************************************************** + * pthread_getschedparam.c + * + * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include +#include +#include +#include +#include "pthread_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + *****************************************************************************/ + +/**************************************************************************** + * Name: pthread_getschedparam + * + * Description: + * The pthread_getschedparam() functions will get the scheduling policy and + * parameters of threads. For SCHED_FIFO and SCHED_RR, the only required + * member of the sched_param structure is the priority sched_priority. + * + * The pthread_getschedparam() function will retrieve the scheduling + * policy and scheduling parameters for the thread whose thread ID is + * given by 'thread' and will store those values in 'policy' and 'param', + * respectively. The priority value returned from pthread_getschedparam() + * will be the value specified by the most recent pthread_setschedparam(), + * pthread_setschedprio(), or pthread_create() call affecting the target + * thread. It will not reflect any temporary adjustments to its priority + * (such as might result of any priority inheritance, for example). + * + * The policy parameter may have the value SCHED_FIFO, or SCHED_RR + * (SCHED_OTHER and SCHED_SPORADIC, in particular, are not supported). + * The SCHED_FIFO and SCHED_RR policies will have a single scheduling + * parameter, sched_priority. +* + * Parameters: + * thread - The ID of thread whose scheduling parameters will be queried. + * policy - The location to store the thread's scheduling policy. + * param - The location to store the thread's priority. + * + * Return Value: + * 0 if successful. Otherwise, the error code ESRCH if the value specified + * by thread does not refer to an existing thread. + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_getschedparam(pthread_t thread, FAR int *policy, + FAR struct sched_param *param) +{ + int ret; + + sdbg("Thread ID=%d policy=0x%p param=0x%p\n", thread, policy, param); + + if (!policy || !param) + { + ret = EINVAL; + } + else + { + /* Get the schedparams of the thread. */ + + ret = sched_getparam((pid_t)thread, param); + if (ret != OK) + { + ret = EINVAL; + } + + /* Return the policy. */ + + *policy = sched_getscheduler((pid_t)thread); + if (*policy == ERROR) + { + ret = get_errno(); + } + } + + sdbg("Returning %d\n", ret); + return ret; +} + diff --git a/nuttx/sched/pthread_getspecific.c b/nuttx/sched/pthread_getspecific.c new file mode 100644 index 000000000..eeead14fa --- /dev/null +++ b/nuttx/sched/pthread_getspecific.c @@ -0,0 +1,123 @@ +/************************************************************************ + * sched/pthread_getspecific.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include + +#include "os_internal.h" +#include "pthread_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: pthread_getspecific + * + * Description: + * The pthread_getspecific() function returns the value currently + * bound to the specified key on behalf of the calling thread. + * + * The effect of calling pthread_getspecific() with with a key value + * not obtained from pthread_create() or after a key has been deleted + * with pthread_key_delete() is undefined. + * + * Parameters: + * key = The data key to get or set + * + * Return Value: + * The function pthread_getspecific() returns the thread-specific data + * associated with the given key. If no thread specific data is + * associated with the key, then the value NULL is returned. + * + * EINVAL - The key value is invalid. + * + * Assumptions: + * + * POSIX Compatibility: + * - Both calling pthread_setspecific() and pthread_getspecific() + * may be called from a thread-specific data destructor + * function. + * + ************************************************************************/ + +FAR void *pthread_getspecific(pthread_key_t key) +{ +#if CONFIG_NPTHREAD_KEYS > 0 + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + FAR void *ret = NULL; + + /* Check if the key is valid. */ + + if (key < g_pthread_num_keys) + { + /* Return the stored value. */ + + ret = rtcb->pthread_data[key]; + } + + return ret; +#else + return NULL; +#endif +} + diff --git a/nuttx/sched/pthread_initialize.c b/nuttx/sched/pthread_initialize.c new file mode 100644 index 000000000..09db1d50e --- /dev/null +++ b/nuttx/sched/pthread_initialize.c @@ -0,0 +1,198 @@ +/**************************************************************************** + * sched/pthread_initialize.c + * + * Copyright (C) 2007-2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include + +#include "pthread_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/* This is the head of a private singly linked list. It + * is used to retain information about the spawned threads. + */ + +FAR join_t *g_pthread_head = NULL; +FAR join_t *g_pthread_tail = NULL; + +/* Mutually exclusive access to this data set is enforced with + * the following (un-named) semaphore. + */ + +sem_t g_join_semaphore; + +/* This keys track of the number of global keys that have been + * allocated. + */ + +uint8_t g_pthread_num_keys; + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_initialize + * + * Description: + * This is an internal OS function called only at power-up boot time. + * + * Parameters: + * None + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +void pthread_initialize(void) +{ + /* Initialize some global variables */ + + g_pthread_head = NULL; + g_pthread_tail = NULL; + g_pthread_num_keys = 0; + + /* Initialize the join semaphore to one (to support one-at- + * a-time access to private data sets). + */ + + (void)sem_init(&g_join_semaphore, 0, 1); +} + +/**************************************************************************** + * Name: pthread_takesemaphore and pthread_givesemaphore + * + * Description: + * Support managed access to the private data sets. + * + * Parameters: + * None + * + * Return Value: + * 0 on success or an ERROR on failure with errno value set to EINVAL. + * Note that the errno EINTR is never returned by this function. + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_takesemaphore(sem_t *sem) +{ + /* Verify input parameters */ + + if (sem) + { + /* Take the semaphore */ + + while (sem_wait(sem) != OK) + { + /* Handle the special case where the semaphore wait was + * awakened by the receipt of a signal. + */ + + if (get_errno() != EINTR) + { + set_errno(EINVAL); + return ERROR; + } + } + return OK; + } + else + { + /* NULL semaphore pointer! */ + + set_errno(EINVAL); + return ERROR; + } +} + +int pthread_givesemaphore(sem_t *sem) +{ + /* Verify input parameters */ + + if (sem) + { + /* Give the semaphore */ + + if (sem_post(sem) == OK) + { + return OK; + } + else + { + /* sem_post() reported an error */ + + set_errno(EINVAL); + return ERROR; + } + } + else + { + /* NULL semaphore pointer! */ + + set_errno(EINVAL); + return ERROR; + } +} + diff --git a/nuttx/sched/pthread_internal.h b/nuttx/sched/pthread_internal.h new file mode 100644 index 000000000..ca70ab291 --- /dev/null +++ b/nuttx/sched/pthread_internal.h @@ -0,0 +1,133 @@ +/**************************************************************************** + * sched/pthread_internal.h + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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. + * + ****************************************************************************/ + +#ifndef __SCHED_PTHREAD_INTERNAL_H +#define __SCHED_PTHREAD_INTERNAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Type Declarations + ****************************************************************************/ + +/* The following defines an entry in the pthread logic's local data set. + * Note that this structure is used to implemented a singly linked list. + * This structure is used (instead of, say, a binary search tree) because + * the data set will be searched using the pid as a key -- a process IDs will + * always be created in a montonically increasing fashion. + */ + +struct join_s +{ + FAR struct join_s *next; /* Implements link list */ + uint8_t crefs; /* Reference count */ + bool started; /* true: pthread started. */ + bool detached; /* true: pthread_detached'ed */ + bool terminated; /* true: detach'ed+exit'ed */ + pthread_t thread; /* Includes pid */ + sem_t exit_sem; /* Implements join */ + sem_t data_sem; /* Implements join */ + pthread_addr_t exit_value; /* Returned data */ + +}; + +typedef struct join_s join_t; + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/* This is the head of a private singly linked list. It is used to retain + * information about the spawned threads. + */ + +extern FAR join_t *g_pthread_head; +extern FAR join_t *g_pthread_tail; + +/* Mutually exclusive access to this data set is enforced with the following + * (un-named) semaphore. + */ + +extern sem_t g_join_semaphore; + +/* This keys track of the number of global keys that have been allocated. */ + +extern uint8_t g_pthread_num_keys; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +EXTERN void weak_function pthread_initialize(void); +EXTERN int pthread_completejoin(pid_t pid, FAR void *exit_value); +EXTERN void pthread_destroyjoin(FAR join_t *pjoin); +EXTERN FAR join_t *pthread_findjoininfo(pid_t pid); +EXTERN int pthread_givesemaphore(sem_t *sem); +EXTERN FAR join_t *pthread_removejoininfo(pid_t pid); +EXTERN int pthread_takesemaphore(sem_t *sem); + +#ifdef CONFIG_MUTEX_TYPES +EXTERN int pthread_mutexattr_verifytype(int type); +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __SCHED_PTHREAD_INTERNAL_H */ + diff --git a/nuttx/sched/pthread_join.c b/nuttx/sched/pthread_join.c new file mode 100644 index 000000000..6a02af352 --- /dev/null +++ b/nuttx/sched/pthread_join.c @@ -0,0 +1,248 @@ +/**************************************************************************** + * pthread_join.c + * + * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include +#include +#include +#include + +#include "os_internal.h" +#include "pthread_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_join + * + * Description: + * A thread can await termination of another thread and retrieve the + * return value of the thread. + * + * Parameters: + * thread + * pexit_value + * + * Return Value: + * 0 if successful. Otherwise, one of the following error codes: + * + * EINVAL The value specified by thread does not refer to ajoinable + * thread. + * ESRCH No thread could be found corresponding to thatspecified by the + * given thread ID. + * EDEADLK A deadlock was detected or the value of thread specifies the + * calling thread. + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_join(pthread_t thread, FAR pthread_addr_t *pexit_value) +{ + FAR join_t *pjoin; + int ret; + + sdbg("thread=%d\n", thread); + + /* First make sure that this is not an attempt to join to + * ourself. + */ + + if ((pid_t)thread == getpid()) + { + return EDEADLK; + } + + /* Make sure no other task is mucking with the data structures + * while we are performing the following operations. NOTE: + * we can be also sure that pthread_exit() will not execute + * because it will also attempt to get this semaphore. + */ + + (void)pthread_takesemaphore(&g_join_semaphore); + + /* Find the join information associated with this thread. + * This can fail for one of three reasons: (1) There is no + * thread associated with 'thread,' (2) the thread is a task + * and does not have join information, or (3) the thread + * was detached and has exitted. + */ + + pjoin = pthread_findjoininfo((pid_t)thread); + if (!pjoin) + { + /* Determine what kind of error to return */ + + FAR _TCB *tcb = sched_gettcb((pthread_t)thread); + + sdbg("Could not find thread data\n"); + + /* Case (1) or (3) -- we can't tell which. Assume (3) */ + + if (!tcb) + { + ret = ESRCH; + } + + /* The thread is still active but has no join info. In that + * case, it must be a task and not a pthread. + */ + + else + { + ret = EINVAL; + } + + (void)pthread_givesemaphore(&g_join_semaphore); + } + else + { + /* We found the join info structure. Increment for the reference + * to the join structure that we have. This will keep things + * stable for we have to do + */ + + sched_lock(); + pjoin->crefs++; + + /* Check if the thread is still running. If not, then things are + * simpler. There are still race conditions to be concerned with. + * For example, there could be multiple threads executing in the + * 'else' block below when we enter! + */ + + if (pjoin->terminated) + { + sdbg("Thread has terminated\n"); + + /* Get the thread exit value from the terminated thread. */ + + if (pexit_value) + { + sdbg("exit_value=0x%p\n", pjoin->exit_value); + *pexit_value = pjoin->exit_value; + } + } + else + { + sdbg("Thread is still running\n"); + + /* Relinquish the data set semaphore. Since pre-emption is + * disabled, we can be certain that no task has the + * opportunity to run between the time we relinquish the + * join semaphore and the time that we wait on the thread exit + * semaphore. + */ + + (void)pthread_givesemaphore(&g_join_semaphore); + + /* Take the thread's thread exit semaphore. We will sleep here + * until the thread exits. We need to exercise caution because + * there could be multiple threads waiting here for the same + * pthread to exit. + */ + + (void)pthread_takesemaphore(&pjoin->exit_sem); + + /* The thread has exited! Get the thread exit value */ + + if (pexit_value) + { + *pexit_value = pjoin->exit_value; + sdbg("exit_value=0x%p\n", pjoin->exit_value); + } + + /* Post the thread's data semaphore so that the exitting thread + * will know that we have received the data. + */ + + (void)pthread_givesemaphore(&pjoin->data_sem); + + /* Retake the join semaphore, we need to hold this when + * pthread_destroyjoin is called. + */ + + (void)pthread_takesemaphore(&g_join_semaphore); + } + + /* Pre-emption is okay now. The logic still cannot be re-entered + * because we hold the join semaphore + */ + + sched_unlock(); + + /* Release our reference to the join structure and, if the reference + * count decrements to zero, deallocate the join structure. + */ + + if (--pjoin->crefs <= 0) + { + (void)pthread_destroyjoin(pjoin); + } + + (void)pthread_givesemaphore(&g_join_semaphore); + ret = OK; + } + + sdbg("Returning %d\n", ret); + return ret; +} + diff --git a/nuttx/sched/pthread_keycreate.c b/nuttx/sched/pthread_keycreate.c new file mode 100644 index 000000000..7579e4c11 --- /dev/null +++ b/nuttx/sched/pthread_keycreate.c @@ -0,0 +1,135 @@ +/**************************************************************************** + * sched/pthread_keycreate.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include + +#include "pthread_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_key_create + * + * Description: + * This function creates a thread-specific data key visible to all threads + * in the system. Although the same key value may be used by different + * threads, the values bound to the key by pthread_setspecific() are + * maintained on a per-thread basis and persist for the life of the calling + * thread. + * + * Upon key creation, the value NULL will be associated with the new key + * in all active threads. Upon thread creation, the value NULL will be + * associated with all defined keys in the new thread. + * + * Parameters: + * key = A pointer to the key to create. + * destructor = An optional destructor() function that may be associated + * with each key that is invoked when a thread exits. However, this + * argument is ignored in the current implementation. + * + * Return Value: + * If successful, the pthread_key_create() function will store the newly + * created key value at *key and return zero (OK). Otherwise, an error + * number will bereturned to indicate the error: + * + * EAGAIN - The system lacked sufficient resources to create another + * thread-specific data key, or the system-imposed limit on the total + * number of keys pers process {PTHREAD_KEYS_MAX} has been exceeded + * ENONMEM - Insufficient memory exists to create the key. + * + * Assumptions: + * + * POSIX Compatibility: + * - The present implementation ignores the destructor argument. + * + ****************************************************************************/ + +int pthread_key_create(FAR pthread_key_t *key, CODE void (*destructor)(void*)) +{ +#if CONFIG_NPTHREAD_KEYS > 0 + int ret = EAGAIN; + + /* Check if we have exceeded the system-defined number of keys. */ + + if (g_pthread_num_keys < PTHREAD_KEYS_MAX) + { + /* Return the key value */ + + *key = g_pthread_num_keys; + + /* Increment the count of global keys. */ + + g_pthread_num_keys++; + + /* Return success. */ + + ret = OK; + } + + return ret; +#else + return ENOSYS; +#endif +} diff --git a/nuttx/sched/pthread_keydelete.c b/nuttx/sched/pthread_keydelete.c new file mode 100644 index 000000000..d55a448ed --- /dev/null +++ b/nuttx/sched/pthread_keydelete.c @@ -0,0 +1,96 @@ +/************************************************************************ + * sched/pthread_keydelete.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include + +#include "pthread_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: pthread_key_delete + * + * Description: + * This POSIX function should delete a thread-specific data key + * previously returned by pthread_key_create(). However, this function + * does nothing in the present implementation. + * + * Parameters: + * key = the key to delete + * + * Return Value: + * Always returns ENOSYSL. + * + * Assumptions: + * + * POSIX Compatibility: + * + ************************************************************************/ + +int pthread_key_delete(pthread_key_t key) +{ + return ENOSYS; +} + diff --git a/nuttx/sched/pthread_kill.c b/nuttx/sched/pthread_kill.c new file mode 100644 index 000000000..5a1506c0c --- /dev/null +++ b/nuttx/sched/pthread_kill.c @@ -0,0 +1,95 @@ +/************************************************************************ + * sched/pthread_kill.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include + +/************************************************************************ + * Global Functions + ************************************************************************/ + +/************************************************************************ + * Name: pthread_kill + * + * Description: + * The pthread_kill() system call can be used to send any signal to a + * thread. See kill() for further information as this is just a simple + * wrapper around the kill() function. + * + * Parameters: + * thread - The id of the thread to receive the signal. Only positive, + * non-zero values of 'thread' are supported. + * signo - The signal number to send. If 'signo' is zero, no signal is + * sent, but all error checking is performed. + * + * Return Value: + * On success the signal was send and zero is returned. On error one + * of the following error numbers is returned. + * + * EINVAL An invalid signal was specified. + * EPERM The thread does not have permission to send the + * signal to the target thread. + * ESRCH No thread could be found corresponding to that + * specified by the given thread ID + * ENOSYS Do not support sending signals to process groups. + * + * Assumptions: + * + ************************************************************************/ + +int pthread_kill(pthread_t thread, int signo) +{ + int ret; + + set_errno(EINVAL); + ret = kill((pid_t)thread, signo); + if (ret != OK) + { + ret = get_errno(); + } + + return ret; +} + + diff --git a/nuttx/sched/pthread_mutexdestroy.c b/nuttx/sched/pthread_mutexdestroy.c new file mode 100644 index 000000000..f66358534 --- /dev/null +++ b/nuttx/sched/pthread_mutexdestroy.c @@ -0,0 +1,131 @@ +/**************************************************************************** + * sched/pthread_mutexdestroy.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include + +#include "pthread_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_mutex_destroy + * + * Description: + * Destroy a mutex. + * + * Parameters: + * None + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_mutex_destroy(FAR pthread_mutex_t *mutex) +{ + int ret = OK; + int status; + + sdbg("mutex=0x%p\n", mutex); + + if (!mutex) + { + ret = EINVAL; + } + else + { + /* Make sure the semaphore is stable while we make the following + * checks + */ + + sched_lock(); + + /* Is the semaphore available? */ + + if (mutex->pid != 0) + { + ret = EBUSY; + } + else + { + /* Destroy the semaphore */ + + status = sem_destroy((sem_t*)&mutex->sem); + if (status != OK) + { + ret = EINVAL; + } + } + + sched_unlock(); + } + + sdbg("Returning %d\n", ret); + return ret; +} diff --git a/nuttx/sched/pthread_mutexinit.c b/nuttx/sched/pthread_mutexinit.c new file mode 100644 index 000000000..265f014e3 --- /dev/null +++ b/nuttx/sched/pthread_mutexinit.c @@ -0,0 +1,138 @@ +/**************************************************************************** + * sched/pthread_mutexinit.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include + +#include "pthread_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_mutex_init + * + * Description: + * Create a mutex + * + * Parameters: + * None + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_mutex_init(FAR pthread_mutex_t *mutex, FAR pthread_mutexattr_t *attr) +{ + int pshared = 0; +#ifdef CONFIG_MUTEX_TYPES + uint8_t type = PTHREAD_MUTEX_DEFAULT; +#endif + int ret = OK; + int status; + + sdbg("mutex=0x%p attr=0x%p\n", mutex, attr); + + if (!mutex) + { + ret = EINVAL; + } + else + { + /* Were attributes specified? If so, use them */ + + if (attr) + { + pshared = attr->pshared; +#ifdef CONFIG_MUTEX_TYPES + type = attr->type; +#endif + } + + /* Indicate that the semaphore is not held by any thread. */ + + mutex->pid = 0; + + /* Initialize the mutex like a semaphore with initial count = 1 */ + + status = sem_init((sem_t*)&mutex->sem, pshared, 1); + if (status != OK) + { + ret = EINVAL; + } + + /* Set up attributes unique to the mutex type */ + +#ifdef CONFIG_MUTEX_TYPES + mutex->type = type; + mutex->nlocks = 0; +#endif + } + + sdbg("Returning %d\n", ret); + return ret; +} diff --git a/nuttx/sched/pthread_mutexlock.c b/nuttx/sched/pthread_mutexlock.c new file mode 100644 index 000000000..7681d771a --- /dev/null +++ b/nuttx/sched/pthread_mutexlock.c @@ -0,0 +1,187 @@ +/**************************************************************************** + * sched/pthread_mutexlock.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include + +#include "pthread_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_mutex_lock + * + * Description: + * The mutex object referenced by mutex is locked by calling + * pthread_mutex_lock(). If the mutex is already locked, the calling thread + * blocks until the mutex becomes available. This operation returns with the + * mutex object referenced by mutex in the locked state with the calling + * thread as its owner. + * + * If the mutex type is PTHREAD_MUTEX_NORMAL, deadlock detection is not + * provided. Attempting to relock the mutex causes deadlock. If a thread + * attempts to unlock a mutex that it has not locked or a mutex which is + * unlocked, undefined behavior results. + * + * If the mutex type is PTHREAD_MUTEX_ERRORCHECK, then error checking is + * provided. If a thread attempts to relock a mutex that it has already + * locked, an error will be returned. If a thread attempts to unlock a + * mutex that it has not locked or a mutex which is unlocked, an error will + * be returned. + * + * If the mutex type is PTHREAD_MUTEX_RECURSIVE, then the mutex maintains + * the concept of a lock count. When a thread successfully acquires a mutex + * for the first time, the lock count is set to one. Every time a thread + * relocks this mutex, the lock count is incremented by one. Each time the + * thread unlocks the mutex, the lock count is decremented by one. When the + * lock count reaches zero, the mutex becomes available for other threads to + * acquire. If a thread attempts to unlock a mutex that it has not locked or + * a mutex which is unlocked, an error will be returned. + * + * If a signal is delivered to a thread waiting for a mutex, upon return + * from the signal handler the thread resumes waiting for the mutex as if + * it was not interrupted. + * + * Parameters: + * mutex - A reference to the mutex to be locked. + * + * Return Value: + * 0 on success or an errno value on failure. Note that the errno EINTR + * is never returned by pthread_mutex_lock(). + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_mutex_lock(FAR pthread_mutex_t *mutex) +{ + int mypid = (int)getpid(); + int ret = OK; + + sdbg("mutex=0x%p\n", mutex); + + if (!mutex) + { + ret = EINVAL; + } + else + { + /* Make sure the semaphore is stable while we make the following + * checks. This all needs to be one atomic action. + */ + + sched_lock(); + + /* Does this task already hold the semaphore? */ + + if (mutex->pid == mypid) + { + /* Yes.. Is this a recursive mutex? */ + +#ifdef CONFIG_MUTEX_TYPES + if (mutex->type == PTHREAD_MUTEX_RECURSIVE) + { + /* Yes... just increment the number of locks held and return success */ + + mutex->nlocks++; + } + else +#endif + { + /* No, then we would deadlock... return an error (default behavior + * is like PTHREAD_MUTEX_ERRORCHECK) + */ + + sdbg("Returning EDEADLK\n"); + ret = EDEADLK; + } + } + else + { + /* Take the semaphore */ + + ret = pthread_takesemaphore((sem_t*)&mutex->sem); + + /* If we succussfully obtained the semaphore, then indicate + * that we own it. + */ + + if (!ret) + { + mutex->pid = mypid; +#ifdef CONFIG_MUTEX_TYPES + mutex->nlocks = 1; +#endif + } + } + + sched_unlock(); + } + + sdbg("Returning %d\n", ret); + return ret; +} + diff --git a/nuttx/sched/pthread_mutextrylock.c b/nuttx/sched/pthread_mutextrylock.c new file mode 100644 index 000000000..d88012b51 --- /dev/null +++ b/nuttx/sched/pthread_mutextrylock.c @@ -0,0 +1,147 @@ +/**************************************************************************** + * sched/pthread_mutextrylock.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include +#include + +#include "pthread_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_mutex_trylock + * + * Description: + * The function pthread_mutex_trylock() is identical to pthread_mutex_lock() + * except that if the mutex object referenced by mutex is currently locked + * (by any thread, including the current thread), the call returns immediately + * with the errno EBUSY. + * + * If a signal is delivered to a thread waiting for a mutex, upon return from + * the signal handler the thread resumes waiting for the mutex as if it was + * not interrupted. + * + * Parameters: + * mutex - A reference to the mutex to be locked. + * + * Return Value: + * 0 on success or an errno value on failure. Note that the errno EINTR + * is never returned by pthread_mutex_lock(). + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_mutex_trylock(FAR pthread_mutex_t *mutex) +{ + int ret = OK; + + sdbg("mutex=0x%p\n", mutex); + + if (!mutex) + { + ret = EINVAL; + } + else + { + /* Make sure the semaphore is stable while we make the following + * checks. This all needs to be one atomic action. + */ + + sched_lock(); + + /* Try to get the semaphore. */ + + if (sem_trywait((sem_t*)&mutex->sem) == OK) + { + /* If we succussfully obtained the semaphore, then indicate + * that we own it. + */ + + mutex->pid = (int)getpid(); + } + + /* Was it not available? */ + + else if (get_errno() == EAGAIN) + { + ret = EBUSY; + } + else + { + ret = EINVAL; + } + + sched_unlock(); + } + + sdbg("Returning %d\n", ret); + return ret; +} + + + diff --git a/nuttx/sched/pthread_mutexunlock.c b/nuttx/sched/pthread_mutexunlock.c new file mode 100644 index 000000000..34846f952 --- /dev/null +++ b/nuttx/sched/pthread_mutexunlock.c @@ -0,0 +1,164 @@ +/**************************************************************************** + * sched/pthread_mutexunlock.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include + +#include "pthread_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_mutex_unlock + * + * Description: + * The pthread_mutex_unlock() function releases the mutex object referenced + * by mutex. The manner in which a mutex is released is dependent upon the + * mutex's type attribute. If there are threads blocked on the mutex object + * referenced by mutex when pthread_mutex_unlock() is called, resulting in + * the mutex becoming available, the scheduling policy is used to determine + * which thread shall acquire the mutex. (In the case of PTHREAD_MUTEX_RECURSIVE + * mutexes, the mutex becomes available when the count reaches zero and the + * calling thread no longer has any locks on this mutex). + * + * If a signal is delivered to a thread waiting for a mutex, upon return from + * the signal handler the thread resumes waiting for the mutex as if it was + * not interrupted. + * + * Parameters: + * None + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_mutex_unlock(FAR pthread_mutex_t *mutex) +{ + int ret = OK; + + sdbg("mutex=0x%p\n", mutex); + + if (!mutex) + { + ret = EINVAL; + } + else + { + /* Make sure the semaphore is stable while we make the following + * checks. This all needs to be one atomic action. + */ + + sched_lock(); + + /* Does the calling thread own the semaphore? */ + + if (mutex->pid != (int)getpid()) + { + /* No... return an error (default behavior is like PTHREAD_MUTEX_ERRORCHECK) */ + + sdbg("Holder=%d returning EPERM\n", mutex->pid); + ret = EPERM; + } + + + /* Yes, the caller owns the semaphore.. Is this a recursive mutex? */ + +#ifdef CONFIG_MUTEX_TYPES + else if (mutex->type == PTHREAD_MUTEX_RECURSIVE && mutex->nlocks > 1) + { + /* This is a recursive mutex and we there are multiple locks held. Retain + * the mutex lock, just decrement the count of locks held, and return + * success. + */ + mutex->nlocks--; + } +#endif + + /* This is either a non-recursive mutex or is the outermost unlock of + * a recursive mutex. + */ + + else + { + /* Nullify the pid and lock count then post the semaphore */ + + mutex->pid = 0; +#ifdef CONFIG_MUTEX_TYPES + mutex->nlocks = 0; +#endif + ret = pthread_givesemaphore((sem_t*)&mutex->sem); + } + sched_unlock(); + } + + sdbg("Returning %d\n", ret); + return ret; +} + + diff --git a/nuttx/sched/pthread_once.c b/nuttx/sched/pthread_once.c new file mode 100644 index 000000000..413300472 --- /dev/null +++ b/nuttx/sched/pthread_once.c @@ -0,0 +1,128 @@ +/******************************************************************************** + * sched/pthread_once.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include + +/******************************************************************************** + * Pre-processor Definitions + ********************************************************************************/ + +/******************************************************************************** + * Private Type Declarations + ********************************************************************************/ + +/******************************************************************************** + * Global Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Function Prototypes + ********************************************************************************/ + +/******************************************************************************** + * Public Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: pthread_once + * + * Description: + * The first call to pthread_once() by any thread with a given once_control, + * will call the init_routine with no arguments. Subsequent calls to + * pthread_once() with the same once_control will have no effect. On return + * from pthread_once(), init_routine will have completed. + * + * Parameters: + * once_control - Determines if init_routine should be called. once_control + * should be declared and intialized as follows: + * + * pthread_once_t once_control = PTHREAD_ONCE_INIT; + * + * PTHREAD_ONCE_INIT is defined in pthread.h + * init_routine - The initialization routine that will be called once. + * + * Return Value: + * 0 (OK) on success or EINVAL if either once_control or init_routine are + * invalid + * + * Assumptions: + * + ********************************************************************************/ + +int pthread_once(FAR pthread_once_t *once_control, + CODE void (*init_routine)(void)) +{ + /* Sanity checks */ + + if (once_control && init_routine) + { + /* Prohibit pre-emption while we test and set the once_control */ + + sched_lock(); + if (!*once_control) + { + *once_control = true; + + /* Call the init_routine with pre-emption enabled. */ + + sched_unlock(); + init_routine(); + return OK; + } + + /* The init_routine has already been called. Restore pre-emption and return */ + + sched_unlock(); + return OK; + } + + /* One of the two arguments is NULL */ + + return EINVAL; +} diff --git a/nuttx/sched/pthread_removejoininfo.c b/nuttx/sched/pthread_removejoininfo.c new file mode 100644 index 000000000..defc02991 --- /dev/null +++ b/nuttx/sched/pthread_removejoininfo.c @@ -0,0 +1,137 @@ +/************************************************************************ + * sched/pthread_removejoininfo.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include "pthread_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: pthread_removejoininfo + * + * Description: + * Remove a join_t from the local data set. + * + * Parameters: + * pid + * + * Return Value: + * None or pointer to the found entry. + * + * Assumptions: + * The caller has provided protection from re-entrancy. + * + ************************************************************************/ + +FAR join_t *pthread_removejoininfo(pid_t pid) +{ + FAR join_t *prev; + FAR join_t *join; + + /* Find the entry with the matching pid */ + + for (prev = NULL, join = g_pthread_head; + (join && (pid_t)join->thread != pid); + prev = join, join = join->next); + + /* Remove it from the data set. */ + + /* First check if this is the entry at the head of the list. */ + + if (join) + { + if (!prev) + { + /* Check if this is the only entry in the list */ + + if (!join->next) + { + g_pthread_head = NULL; + g_pthread_tail = NULL; + } + + /* Otherwise, remove it from the head of the list */ + + else + { + g_pthread_head = join->next; + } + } + + /* It is not at the head of the list, check if it is at the tail. */ + + else if (!join->next) + { + g_pthread_tail = prev; + prev->next = NULL; + } + + /* No, remove it from the middle of the list. */ + + else + { + prev->next = join->next; + } + } + + return join; +} + diff --git a/nuttx/sched/pthread_setcancelstate.c b/nuttx/sched/pthread_setcancelstate.c new file mode 100644 index 000000000..2c6bf3083 --- /dev/null +++ b/nuttx/sched/pthread_setcancelstate.c @@ -0,0 +1,131 @@ +/****************************************************************************************** + * pthread_setcancelstate.c + * + * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include +#include "os_internal.h" + +/****************************************************************************************** + * Private Definitions + ******************************************************************************************/ + +/****************************************************************************************** + * Private Types + ******************************************************************************************/ + +/****************************************************************************************** + * Private Function Prototypes + ******************************************************************************************/ + +/****************************************************************************************** + * Global Variables + ******************************************************************************************/ + +/****************************************************************************************** + * Private Variables + ******************************************************************************************/ + +/****************************************************************************************** + * Private Functions + ******************************************************************************************/ + +/****************************************************************************************** + * Public Functions + ******************************************************************************************/ + +/****************************************************************************************** + * Name: pthread_setcancelstate + ******************************************************************************************/ + +int pthread_setcancelstate(int state, FAR int *oldstate) +{ + _TCB *tcb = (_TCB*)g_readytorun.head; + int ret = OK; + + /* Suppress context changes for a bit so that the flags are stable. (the + * flags should not change in interrupt handling). + */ + + sched_lock(); + + /* Return the current state if so requrested */ + + if (oldstate) + { + if ((tcb->flags & TCB_FLAG_NONCANCELABLE) != 0) + { + *oldstate = PTHREAD_CANCEL_DISABLE; + } + else + { + *oldstate = PTHREAD_CANCEL_ENABLE; + } + } + + /* Set the new cancellation state */ + + if (state == PTHREAD_CANCEL_ENABLE) + { + unsigned flags = tcb->flags; + + /* Clear the non-cancelable and cancel pending flags */ + + tcb->flags &= ~(TCB_FLAG_NONCANCELABLE|TCB_FLAG_CANCEL_PENDING); + + /* If the cancel was pending, then just exit as requested */ + + if (flags & TCB_FLAG_CANCEL_PENDING) + { + pthread_exit(PTHREAD_CANCELED); + } + } + else if (state == PTHREAD_CANCEL_DISABLE) + { + /* Set the non-cancelable state */ + + tcb->flags |= TCB_FLAG_NONCANCELABLE; + } + else + { + ret = EINVAL; + } + + sched_unlock(); + return ret; +} diff --git a/nuttx/sched/pthread_setschedparam.c b/nuttx/sched/pthread_setschedparam.c new file mode 100644 index 000000000..019a7c7a5 --- /dev/null +++ b/nuttx/sched/pthread_setschedparam.c @@ -0,0 +1,142 @@ +/**************************************************************************** + * pthread_setschedparam.c + * + * Copyright (C) 2007, 2008, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include +#include +#include +#include + +#include "pthread_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_setschedparam + * + * Description: + * The pthread_setschedparam() functions will set the scheduling policy + * and parameters of threads. For SCHED_FIFO and SCHED_RR, the only + * required member of the sched_param structure is the priority + * sched_priority. + * + * The pthread_setschedparam() function will set the scheduling policy + * and associated scheduling parameters for the thread whose thread ID + * is given by 'thread' to the policy and associated parameters provided + * in 'policy' and 'param', respectively. + * + * The policy parameter may have the value SCHED_FIFO, or SCHED_RR + * (SCHED_OTHER and SCHED_SPORADIC, in particular, are not supported). + * The SCHED_FIFO and SCHED_RR policies will have a single scheduling + * parameter, sched_priority. + * + * If the pthread_setschedparam() function fails, the scheduling parameters + * will not be changed for the target thread. + * + * Parameters: + * thread - The ID of thread whose scheduling parameters will be modified. + * policy - The new scheduling policy of the thread. Either SCHED_FIFO or + * SCHED_RR. SCHED_OTHER and SCHED_SPORADIC are not supported. + * param - Provides the new priority of the thread. + * + * Return Value: + * 0 if successful. Otherwise, an error code identifying the cause of the + * failure: + * + * EINVAL The value specified by 'policy' or one of the scheduling + * parameters associated with the scheduling policy 'policy' is + * invalid. + * ENOTSUP An attempt was made to set the policy or scheduling parameters + * to an unsupported value (SCHED_OTHER and SCHED_SPORADIC in + * particular are not supported) + * EPERM The caller does not have the appropriate permission to set either + * the scheduling parameters or the scheduling policy of the + * specified thread. Or, the implementation does not allow the + * application to modify one of the parameters to the value + * specified. + * ESRCH The value specified by thread does not refer to a existing thread. + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_setschedparam(pthread_t thread, int policy, FAR const struct sched_param *param) +{ + int ret; + + sdbg("thread ID=%d policy=%d param=0x%p\n", thread, policy, param); + + /* Set the errno to some non-zero value (failsafe) */ + + set_errno(EINVAL); + + /* Let sched_setscheduler do all of the work */ + + ret = sched_setscheduler((pid_t)thread, policy, param); + if (ret != OK) + { + /* If sched_setscheduler() fails, return the errno */ + + ret = get_errno(); + } + + return ret; +} diff --git a/nuttx/sched/pthread_setschedprio.c b/nuttx/sched/pthread_setschedprio.c new file mode 100644 index 000000000..a523b20ea --- /dev/null +++ b/nuttx/sched/pthread_setschedprio.c @@ -0,0 +1,120 @@ +/**************************************************************************** + * pthread_schedsetprio.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include +#include +#include +#include +#include "os_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_setsetprio + * + * Description: + * The pthread_setschedprio() function sets the scheduling priority for the + * thread whose thread ID is given by 'thread' to the value given by 'prio'. + * If the thread_setschedprio() function fails, the scheduling priority + * of the target thread will not be changed. + * + * Inputs: + * thread - the thread ID of the task to reprioritize. + * prio - The new thread priority. The range of valid priority numbers is + * from SCHED_PRIORITY_MIN through SCHED_PRIORITY_MAX. + * + * Return Value: + * OK if successful, otherwise an error number. This function can + * fail for the following reasons: + * + * EINVAL - prio is out of range. + * ESRCH - thread ID does not correspond to any thread. + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_setschedprio(pthread_t thread, int prio) +{ + struct sched_param param; + int ret; + + /* Set the errno to some non-zero value (failsafe) */ + + errno = EINVAL; + + /* Call sched_setparam() to change the priority */ + + param.sched_priority = prio; + ret = sched_setparam((pid_t)thread, ¶m); + if (ret != OK) + { + /* If sched_setparam() fails, return the errno */ + + ret = errno; + } + return ret; +} diff --git a/nuttx/sched/pthread_setspecific.c b/nuttx/sched/pthread_setspecific.c new file mode 100644 index 000000000..33fb4aeeb --- /dev/null +++ b/nuttx/sched/pthread_setspecific.c @@ -0,0 +1,137 @@ +/**************************************************************************** + * sched/pthread_setspecific.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include "os_internal.h" +#include "pthread_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_setspecific + * + * Description: + * The pthread_setspecific() function associates a thread- + * specific value with a key obtained via a previous call + * to pthread_key_create(). Different threads may bind + * different values to the same key. These values are + * typically pointers to blocks of dynamically allocated + * memory that have been reserved for use by the calling + * thread. + * + * The effect of calling pthread_setspecific() with + * with a key value not obtained from pthread_create() or + * after a key has been deleted with pthread_key_delete() + * is undefined. + * + * Parameters: + * key = The data key to get or set + * value = The value to bind to the key. + * + * Return Value: + * If successful, pthread_setspecific() will return zero (OK). + * Otherwise, an error number will be returned: + * + * ENOMEM - Insufficient memory exists to associate + * the value with the key. + * EINVAL - The key value is invalid. + * + * Assumptions: + * + * POSIX Compatibility: + * int pthread_setspecific(pthread_key_t key, void *value) + * void *pthread_getspecific(pthread_key_t key) + * + * - Both calling pthread_setspecific() and pthread_getspecific() + * may be called from a thread-specific data destructor + * function. + * + ****************************************************************************/ + +int pthread_setspecific(pthread_key_t key, FAR void *value) +{ +#if CONFIG_NPTHREAD_KEYS > 0 + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + int ret = EINVAL; + + /* Check if the key is valid. */ + + if (key < g_pthread_num_keys) + { + /* Store the data in the TCB. */ + + rtcb->pthread_data[key] = value; + + /* Return success. */ + + ret = OK; + } + + return ret; +#else + return ENOSYS; +#endif +} + diff --git a/nuttx/sched/pthread_sigmask.c b/nuttx/sched/pthread_sigmask.c new file mode 100644 index 000000000..c66b8591c --- /dev/null +++ b/nuttx/sched/pthread_sigmask.c @@ -0,0 +1,107 @@ +/************************************************************************ + * sched/pthread_sigmask.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: pthread_sigmask + * + * Description: + * This function is a simple wrapper around sigprocmask(). + * See the sigprocmask() function description for further + * information. + * + * Parameters: + * how - How the signal mast will be changed: + * SIG_BLOCK - The resulting set is the union of + * the current set and the signal set + * pointed to by 'set'. + * SIG_UNBLOCK - The resulting set is the intersection + * of the current set and the complement + * of the signal set pointed to by 'set'. + * SIG_SETMASK - The resulting set is the signal set + * pointed to by 'set'. + * set - Location of the new signal mask + * oset - Location to store the old signal mask + * + * Return Value: + * 0 (OK) or EINVAL if how is invalid. + * + * Assumptions: + * + ************************************************************************/ + +int pthread_sigmask(int how, FAR const sigset_t *set, FAR sigset_t *oset) +{ + int ret = sigprocmask(how, set, oset); + if (ret != OK) + { + ret = EINVAL; + } + return ret; +} diff --git a/nuttx/sched/pthread_yield.c b/nuttx/sched/pthread_yield.c new file mode 100644 index 000000000..c4535b9db --- /dev/null +++ b/nuttx/sched/pthread_yield.c @@ -0,0 +1,87 @@ +/************************************************************************ + * sched/pthread_yield.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: pthread_yield + * + * Description: + * A thread may tell the scheduler that its processor can be + * made available. + * + * Parameters: + * None + * + * Return Value: + * None + * + * Assumptions: + * + ************************************************************************/ + +void pthread_yield(void) +{ + (void)sched_yield(); +} diff --git a/nuttx/sched/sched_addblocked.c b/nuttx/sched/sched_addblocked.c new file mode 100644 index 000000000..c0b80c8ac --- /dev/null +++ b/nuttx/sched/sched_addblocked.c @@ -0,0 +1,122 @@ +/************************************************************************ + * sched/sched_addblocked.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include + +#include "os_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sched_addblocked + * + * Description: + * This function adds a TCB to one of the blocked state task lists as + * inferred from task_state. + * + * Inputs: + * btcb - Points to the TCB that is blocked + * task_state - identifies the state of the blocked task + * + * Return Value: + * None + * + * Assumptions: + * - The caller has established a critical section before + * calling this function. + * + ************************************************************************/ + +void sched_addblocked(FAR _TCB *btcb, tstate_t task_state) +{ + /* Make sure that we received a valid blocked state */ + + ASSERT(task_state >= FIRST_BLOCKED_STATE && + task_state <= LAST_BLOCKED_STATE); + + /* Add the TCB to the blocked task list associated with this state. + * First, determine if the task is to be added to a prioritized task + * list + */ + + if (g_tasklisttable[task_state].prioritized) + { + /* Add the task to a prioritized list */ + + sched_addprioritized(btcb, + (FAR dq_queue_t*)g_tasklisttable[task_state].list); + } + else + { + /* Add the task to a non-prioritized list */ + + dq_addlast((FAR dq_entry_t*)btcb, + (FAR dq_queue_t*)g_tasklisttable[task_state].list); + } + + /* Make sure the TCB's state corresponds to the list */ + + btcb->task_state = task_state; +} + diff --git a/nuttx/sched/sched_addprioritized.c b/nuttx/sched/sched_addprioritized.c new file mode 100644 index 000000000..8f19a4731 --- /dev/null +++ b/nuttx/sched/sched_addprioritized.c @@ -0,0 +1,175 @@ +/************************************************************************ + * sched/sched_addprioritized.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include + +#include "os_internal.h" + +/************************************************************************ + * Pre-processor Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sched_addprioritized + * + * Description: + * This function adds a TCB to a prioritized TCB list. + * + * Inputs: + * tcb - Points to the TCB to add to the prioritized list + * list - Points to the prioritized list to add tcb to + * + * Return Value: + * true if the head of the list has changed. + * + * Assumptions: + * - The caller has established a critical section before + * calling this function (calling sched_lock() first is NOT + * a good idea -- use irqsave()). + * - The caller has already removed the input tcb from + * whatever list it was in. + * - The caller handles the condition that occurs if the + * the head of the task list is changed. + * - The caller must set the task_state field of the TCB to + * match the state associated with the list. + ************************************************************************/ + +bool sched_addprioritized(FAR _TCB *tcb, DSEG dq_queue_t *list) +{ + FAR _TCB *next; + FAR _TCB *prev; + uint8_t sched_priority = tcb->sched_priority; + bool ret = false; + + /* Lets do a sanity check before we get started. */ + + ASSERT(sched_priority >= SCHED_PRIORITY_MIN); + + /* Search the list to find the location to insert the new Tcb. + * Each is list is maintained in ascending sched_priority order. + */ + + for (next = (FAR _TCB*)list->head; + (next && sched_priority <= next->sched_priority); + next = next->flink); + + /* Add the tcb to the spot found in the list. Check if the tcb + * goes at the end of the list. NOTE: This could only happen if list + * is the g_pendingtasks list! + */ + + if (!next) + { + /* The tcb goes at the end of the list. */ + + prev = (FAR _TCB*)list->tail; + if (!prev) + { + /* Special case: The list is empty */ + + tcb->flink = NULL; + tcb->blink = NULL; + list->head = (FAR dq_entry_t*)tcb; + list->tail = (FAR dq_entry_t*)tcb; + ret = true; + } + else + { + /* The tcb goes at the end of a non-empty list */ + + tcb->flink = NULL; + tcb->blink = prev; + prev->flink = tcb; + list->tail = (FAR dq_entry_t*)tcb; + } + } + else + { + /* The tcb goes just before next */ + + prev = (FAR _TCB*)next->blink; + if (!prev) + { + /* Special case: Insert at the head of the list */ + + tcb->flink = next; + tcb->blink = NULL; + next->blink = tcb; + list->head = (FAR dq_entry_t*)tcb; + ret = true; + } + else + { + /* Insert in the middle of the list */ + + tcb->flink = next; + tcb->blink = prev; + prev->flink = tcb; + next->blink = tcb; + } + } + + return ret; +} + diff --git a/nuttx/sched/sched_addreadytorun.c b/nuttx/sched/sched_addreadytorun.c new file mode 100644 index 000000000..f6117b6ff --- /dev/null +++ b/nuttx/sched/sched_addreadytorun.c @@ -0,0 +1,149 @@ +/**************************************************************************** + * sched/sched_addreadytorun.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include + +#include "os_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sched_addreadytorun + * + * Description: + * This function adds a TCB to the ready to run + * list. If the currently active task has preemption disabled + * and the new TCB would cause this task to be preempted, the + * new task is added to the g_pendingtasks list instead. The + * pending tasks will be made ready-to-run when preemption + * is unlocked. + * + * Inputs: + * btcb - Points to the blocked TCB that is ready-to-run + * + * Return Value: + * true if the currently active task (the head of the + * g_readytorun list) has changed. + * + * Assumptions: + * - The caller has established a critical section before + * calling this function (calling sched_lock() first is NOT + * a good idea -- use irqsave()). + * - The caller has already removed the input rtcb from + * whatever list it was in. + * - The caller handles the condition that occurs if the + * the head of the g_readytorun list is changed. + * + ****************************************************************************/ + +bool sched_addreadytorun(FAR _TCB *btcb) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + bool ret; + + /* Check if pre-emption is disabled for the current running task and if + * the new ready-to-run task would cause the current running task to be + * preempted. + */ + + if (rtcb->lockcount && rtcb->sched_priority < btcb->sched_priority) + { + /* Yes. Preemption would occur! Add the new ready-to-run task to the + * g_pendingtasks task list for now. + */ + + sched_addprioritized(btcb, (FAR dq_queue_t*)&g_pendingtasks); + btcb->task_state = TSTATE_TASK_PENDING; + ret = false; + } + + /* Otherwise, add the new task to the g_readytorun task list */ + + else if (sched_addprioritized(btcb, (FAR dq_queue_t*)&g_readytorun)) + { + /* Information the instrumentation logic that we are switching tasks */ + + sched_note_switch(rtcb, btcb); + + /* The new btcb was added at the head of the g_readytorun list. It + * is now to new active task! + */ + + ASSERT(!rtcb->lockcount && btcb->flink != NULL); + + btcb->task_state = TSTATE_TASK_RUNNING; + btcb->flink->task_state = TSTATE_TASK_READYTORUN; + ret = true; + } + else + { + /* The new btcb was added in the middle of the g_readytorun list */ + + btcb->task_state = TSTATE_TASK_READYTORUN; + ret = false; + } + + return ret; +} diff --git a/nuttx/sched/sched_foreach.c b/nuttx/sched/sched_foreach.c new file mode 100644 index 000000000..192094533 --- /dev/null +++ b/nuttx/sched/sched_foreach.c @@ -0,0 +1,84 @@ +/************************************************************************ + * sched/sched_foreach.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include "os_internal.h" + +/************************************************************************ + * Global Functions + ************************************************************************/ + +/************************************************************************ + * Name: sched_foreach + * + * Description: + * Enumerate over each task and provide the TCB of each + * task to a user callback functions. Interrupts will be + * disabled throughout this enumeration! + * + * Parameters: + * handler - The function to be called with the TCB of + * each task + * + * Return Value: + * None + * + * Assumptions: + * + ************************************************************************/ + +void sched_foreach(sched_foreach_t handler, FAR void *arg) +{ + irqstate_t flags = irqsave(); + int ndx; + + /* Verify that the PID is within range */ + + for (ndx = 0; ndx < CONFIG_MAX_TASKS; ndx++) + { + if (g_pidhash[ndx].tcb) + { + handler(g_pidhash[ndx].tcb, arg); + } + } + + irqrestore(flags); +} + + diff --git a/nuttx/sched/sched_free.c b/nuttx/sched/sched_free.c new file mode 100644 index 000000000..e5e0bdacf --- /dev/null +++ b/nuttx/sched/sched_free.c @@ -0,0 +1,114 @@ +/************************************************************************ + * sched/sched_free.c + * + * Copyright (C) 2007, 2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include + +#include +#include +#include +#include "os_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sched_free + * + * Description: + * This function performs deallocations that the operating system may + * need to make. This special interface to free is used to handling + * corner cases where the operating system may have to perform + * deallocations from within an interrupt handler. + * + ************************************************************************/ + +void sched_free(FAR void *address) +{ + /* Check if this is an attempt to deallocate memory from an exception + * handler. If this function is called from the IDLE task, then we + * must have exclusive access to the memory manager to do this. + */ + + if (up_interrupt_context() || kmm_trysemaphore() != 0) + { + /* Yes.. Delay the deallocation until a more appropriate time. */ + + irqstate_t saved_state = irqsave(); + sq_addlast((FAR sq_entry_t*)address, (sq_queue_t*)&g_delayeddeallocations); + + /* Signal the worker thread that is has some clean up to do */ + +#ifdef CONFIG_SCHED_WORKQUEUE + work_signal(LPWORK); +#endif + irqrestore(saved_state); + } + else + { + /* No.. just deallocate the memory now. */ + + kfree(address); + kmm_givesemaphore(); + } +} + diff --git a/nuttx/sched/sched_garbage.c b/nuttx/sched/sched_garbage.c new file mode 100644 index 000000000..b8bec9399 --- /dev/null +++ b/nuttx/sched/sched_garbage.c @@ -0,0 +1,117 @@ +/**************************************************************************** + * sched/sched_garbage.c + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include + +#include "os_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ +/**************************************************************************** + * Name: sched_garbagecollection + * + * Description: + * Clean-up memory de-allocations that we queued because they could not + * be freed in that execution context (for example, if the memory was freed + * from an interrupt handler). + * + * This logic may be called from the worker thread (see work_thread.c). + * If, however, CONFIG_SCHED_WORKQUEUE is not defined, then this logic will + * be called from the IDLE thread. It is less optimal for the garbage + * collection to be called from the IDLE thread because it runs at a very + * low priority and could cause false memory out conditions. + * + * Input parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void sched_garbagecollection(void) +{ + irqstate_t flags; + void *address; + + /* Test if the delayed deallocation queue is empty. No special protection + * is needed because this is an atomic test. + */ + + while (g_delayeddeallocations.head) + { + /* Remove the first delayed deallocation. This is not atomic and so + * we must disable interrupts around the queue operation. + */ + + flags = irqsave(); + address = (void*)sq_remfirst((FAR sq_queue_t*)&g_delayeddeallocations); + irqrestore(flags); + + /* Then deallocate it. */ + + if (address) + { + kfree(address); + } + } +} + diff --git a/nuttx/sched/sched_getfiles.c b/nuttx/sched/sched_getfiles.c new file mode 100644 index 000000000..256b4cb6b --- /dev/null +++ b/nuttx/sched/sched_getfiles.c @@ -0,0 +1,76 @@ +/************************************************************************ + * sched/sched_getfiles.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include +#include "os_internal.h" + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sched_getfiles + * + * Description: + * Return a pointer to the file list for this thread + * + * Parameters: + * None + * + * Return Value: + * A pointer to the errno. + * + * Assumptions: + * + ************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 + +FAR struct filelist *sched_getfiles(void) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + return rtcb->filelist; +} + +#endif /* CONFIG_NFILE_DESCRIPTORS */ diff --git a/nuttx/sched/sched_getparam.c b/nuttx/sched/sched_getparam.c new file mode 100644 index 000000000..47eab4988 --- /dev/null +++ b/nuttx/sched/sched_getparam.c @@ -0,0 +1,146 @@ +/************************************************************************ + * sched/sched_getparam.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include + +#include "os_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sched_getparam + * + * Description: + * This function gets the scheduling priority of the task + * specified by pid. + * + * Inputs: + * pid - the task ID of the task. If pid is zero, the priority + * of the calling task is returned. + * param - A structure whose member sched_priority is the integer + * priority. The task's priority is copied to the sched_priority + * element of this structure. + * + * Return Value: + * 0 (OK) if successful, otherwise -1 (ERROR). + * + * This function can fail if param is null or if pid does + * not correspond to any task. + * + * Assumptions: + * + ************************************************************************/ + +int sched_getparam (pid_t pid, struct sched_param * param) +{ + FAR _TCB *rtcb; + FAR _TCB *tcb; + int ret = OK; + + if (!param) + { + return ERROR; + } + + /* Check if the task to restart is the calling task */ + + rtcb = (FAR _TCB*)g_readytorun.head; + if ((pid == 0) || (pid == rtcb->pid)) + { + /* Return the priority if the calling task. */ + + param->sched_priority = (int)rtcb->sched_priority; + } + + /* Ths pid is not for the calling task, we will have to look it up */ + + else + { + /* Get the TCB associated with this pid */ + + sched_lock(); + tcb = sched_gettcb(pid); + if (!tcb) + { + /* This pid does not correspond to any known task */ + + ret = ERROR; + } + else + { + /* Return the priority of the task */ + + param->sched_priority = (int)tcb->sched_priority; + } + + sched_unlock(); + } + + return ret; +} + diff --git a/nuttx/sched/sched_getscheduler.c b/nuttx/sched/sched_getscheduler.c new file mode 100644 index 000000000..5771e86ff --- /dev/null +++ b/nuttx/sched/sched_getscheduler.c @@ -0,0 +1,131 @@ +/************************************************************************ + * sched/sched_getscheduler.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include + +#include + +#include "os_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sched_getscheduler + * + * Description: + * sched_getscheduler() returns the scheduling policy currently + * applied to the task identified by pid. If pid equals zero, the + * policy of the calling task will be retrieved. + * + * Inputs: + * pid - the task ID of the task to query. If pid is zero, the + * calling task is queried. + * + * Return Value: + * On success, sched_getscheduler() returns the policy for the task + * (either SCHED_FIFO or SCHED_RR). On error, ERROR (-1) is + * returned, and errno is set appropriately: + * + * ESRCH The task whose ID is pid could not be found. + * + * Assumptions: + * + ************************************************************************/ + +int sched_getscheduler(pid_t pid) +{ + _TCB *tcb; + + /* Verify that the pid corresponds to a real task */ + + if (!pid) + { + tcb = (_TCB*)g_readytorun.head; + } + else + { + tcb = sched_gettcb(pid); + } + + if (!tcb) + { + set_errno(ESRCH); + return ERROR; + } +#if CONFIG_RR_INTERVAL > 0 + else if ((tcb->flags & TCB_FLAG_ROUND_ROBIN) != 0) + { + return SCHED_RR; + } +#endif + else + { + return SCHED_FIFO; + } +} diff --git a/nuttx/sched/sched_getsockets.c b/nuttx/sched/sched_getsockets.c new file mode 100644 index 000000000..cd499420f --- /dev/null +++ b/nuttx/sched/sched_getsockets.c @@ -0,0 +1,77 @@ +/************************************************************************ + * sched/sched_getsockets.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include "os_internal.h" + +#if CONFIG_NSOCKET_DESCRIPTORS > 0 + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sched_getsockets + * + * Description: + * Return a pointer to the socket list for this thread + * + * Parameters: + * None + * + * Return Value: + * A pointer to the errno. + * + * Assumptions: + * + ************************************************************************/ + +FAR struct socketlist *sched_getsockets(void) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + return rtcb->sockets; +} + +#endif /* CONFIG_NSOCKET_DESCRIPTORS */ diff --git a/nuttx/sched/sched_getstreams.c b/nuttx/sched/sched_getstreams.c new file mode 100644 index 000000000..f7c21ab4c --- /dev/null +++ b/nuttx/sched/sched_getstreams.c @@ -0,0 +1,76 @@ +/**************************************************************************** + * sched/sched_getstreams.c + * + * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include +#include "os_internal.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sched_getstreams + * + * Description: + * Return a pointer to the streams list for this thread + * + * Parameters: + * None + * + * Return Value: + * A pointer to the errno. + * + * Assumptions: + * + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NFILE_STREAMS > 0 + +FAR struct streamlist *sched_getstreams(void) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + return rtcb->streams; +} + +#endif /* CONFIG_NFILE_DESCRIPTORS && CONFIG_NFILE_STREAMS */ diff --git a/nuttx/sched/sched_gettcb.c b/nuttx/sched/sched_gettcb.c new file mode 100644 index 000000000..1e50ef50f --- /dev/null +++ b/nuttx/sched/sched_gettcb.c @@ -0,0 +1,107 @@ +/**************************************************************************** + * sched/sched_gettcb.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include + +#include "os_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sched_gettcb + * + * Description: + * Given a task ID, this function will return + * the a pointer to the corresponding TCB (or NULL if there + * is no such task ID). + * + ****************************************************************************/ + +FAR _TCB *sched_gettcb(pid_t pid) +{ + FAR _TCB *ret = NULL; + int hash_ndx; + + /* Verify that the PID is within range */ + + if (pid >= 0 ) + { + /* Get the hash_ndx associated with the pid */ + + hash_ndx = PIDHASH(pid); + + /* Verify that the correct TCB was found. */ + + if (pid == g_pidhash[hash_ndx].pid) + { + /* Return the TCB associated with this pid (if any) */ + + ret = g_pidhash[hash_ndx].tcb; + } + } + + /* Return the TCB. */ + + return ret; +} + diff --git a/nuttx/sched/sched_lock.c b/nuttx/sched/sched_lock.c new file mode 100644 index 000000000..61a8a3bc8 --- /dev/null +++ b/nuttx/sched/sched_lock.c @@ -0,0 +1,110 @@ +/************************************************************************ + * sched/sched_lock.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include + +#include +#include "os_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/************************************************************************ + * Private Functionss + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sched_lock + * + * Description: + * This function disables context switching by disabling addition of + * new tasks to the g_readytorun task list. The task that calls this + * function will be the only task that is allowed to run until it + * either calls sched_unlock() (the appropriate number of times) or + * until it blocks itself. + * + * Inputs + * None + * + * Return Value: + * OK on success; ERROR on failure + * + ************************************************************************/ + +int sched_lock(void) +{ + _TCB *rtcb = (_TCB*)g_readytorun.head; + + /* Check for some special cases: (1) rtcb may be NULL only during + * early boot-up phases, and (2) sched_lock() should have no + * effect if called from the interrupt level. + */ + + if (rtcb && !up_interrupt_context()) + { + ASSERT(rtcb->lockcount < MAX_LOCK_COUNT); + rtcb->lockcount++; + } + + return OK; +} diff --git a/nuttx/sched/sched_lockcount.c b/nuttx/sched/sched_lockcount.c new file mode 100644 index 000000000..4dc7a8201 --- /dev/null +++ b/nuttx/sched/sched_lockcount.c @@ -0,0 +1,97 @@ +/************************************************************************ + * sched/sched_lockcount.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include + +#include "os_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/************************************************************************ + * Private Functionss + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sched_lockcount + * + * Description: + * This function returns the current value of the lockcount. If zero, + * pre-emption is enabled; if non-zero, this value indicates the number + * of times that sched_lock() has been called on this thread of + * execution. sched_unlock() will have to called that many times from + * this thread in order to re-enable pre-emption. + * + * Inputs: + * None + * + * Return Value: + * lockcount + * + ************************************************************************/ + +int sched_lockcount(void) +{ + _TCB *rtcb = (_TCB*)g_readytorun.head; + return (int)rtcb->lockcount; +} + diff --git a/nuttx/sched/sched_mergepending.c b/nuttx/sched/sched_mergepending.c new file mode 100644 index 000000000..71d575c23 --- /dev/null +++ b/nuttx/sched/sched_mergepending.c @@ -0,0 +1,177 @@ +/************************************************************************ + * sched/sched_mergepending.c + * + * Copyright (C) 2007, 2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include + +#include "os_internal.h" + +/************************************************************************ + * Pre-processor Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sched_mergepending + * + * Description: + * This function merges the prioritized g_pendingtasks list into the + * prioritized g_readytorun task list. + * + * Inputs: + * None + * + * Return Value: + * true if the head of the g_readytorun task list has changed. + * + * Assumptions: + * - The caller has established a critical section before + * calling this function (calling sched_lock() first is NOT + * a good idea -- use irqsave()). + * - The caller handles the condition that occurs if the + * the head of the sched_mergTSTATE_TASK_PENDINGs is changed. + * + ************************************************************************/ + +bool sched_mergepending(void) +{ + FAR _TCB *pndtcb; + FAR _TCB *pndnext; + FAR _TCB *rtrtcb; + FAR _TCB *rtrprev; + bool ret = false; + + /* Initialize the inner search loop */ + + rtrtcb = (FAR _TCB*)g_readytorun.head; + + /* Process every TCB in the g_pendingtasks list */ + + for (pndtcb = (FAR _TCB*)g_pendingtasks.head; pndtcb; pndtcb = pndnext) + { + pndnext = pndtcb->flink; + + /* Search the g_readytorun list to find the location to insert the + * new pndtcb. Each is list is maintained in ascending sched_priority + * order. + */ + + for (; + (rtrtcb && pndtcb->sched_priority <= rtrtcb->sched_priority); + rtrtcb = rtrtcb->flink); + + /* Add the pndtcb to the spot found in the list. Check if the + * pndtcb goes at the ends of the g_readytorun list. This would be + * error condition since the idle test must always be at the end of + * the g_readytorun list! + */ + + if (!rtrtcb) + { + PANIC(OSERR_NOIDLETASK); + } + else + { + /* The pndtcb goes just before rtrtcb */ + + rtrprev = rtrtcb->blink; + if (!rtrprev) + { + /* Special case: Inserting pndtcb at the head of the list */ + /* Inform the instrumentation layer that we are switching tasks */ + + sched_note_switch(rtrtcb, pndtcb); + + /* Then insert at the head of the list */ + + pndtcb->flink = rtrtcb; + pndtcb->blink = NULL; + rtrtcb->blink = pndtcb; + g_readytorun.head = (FAR dq_entry_t*)pndtcb; + rtrtcb->task_state = TSTATE_TASK_READYTORUN; + pndtcb->task_state = TSTATE_TASK_RUNNING; + ret = true; + } + else + { + /* Insert in the middle of the list */ + + pndtcb->flink = rtrtcb; + pndtcb->blink = rtrprev; + rtrprev->flink = pndtcb; + rtrtcb->blink = pndtcb; + pndtcb->task_state = TSTATE_TASK_READYTORUN; + } + } + + /* Set up for the next time through */ + + rtrtcb = pndtcb; + } + + /* Mark the input list empty */ + + g_pendingtasks.head = NULL; + g_pendingtasks.tail = NULL; + + return ret; +} diff --git a/nuttx/sched/sched_processtimer.c b/nuttx/sched/sched_processtimer.c new file mode 100644 index 000000000..2224b7691 --- /dev/null +++ b/nuttx/sched/sched_processtimer.c @@ -0,0 +1,190 @@ +/************************************************************************ + * sched/sched_processtimer.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include + +#if CONFIG_RR_INTERVAL > 0 +# include +# include +#endif + +#include "os_internal.h" +#include "wd_internal.h" +#include "clock_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +static void sched_process_timeslice(void) +{ +#if CONFIG_RR_INTERVAL > 0 + _TCB *rtcb; + + /* Check if the currently executing task uses round robin + * scheduling. + */ + + rtcb = (_TCB*)g_readytorun.head; + if ((rtcb->flags & TCB_FLAG_ROUND_ROBIN) != 0) + { + /* Yes, check if decrementing the timeslice counter + * would cause the timeslice to expire + */ + + if (rtcb->timeslice <= 1) + { + /* Yes, Now check if the task has pre-emption disabled. + * If so, then we will freeze the timeslice count at + * the value until the next tick after pre-emption + * has been enabled. + */ + + if (!rtcb->lockcount) + { + /* Reset the timeslice in any case. */ + + rtcb->timeslice = CONFIG_RR_INTERVAL / MSEC_PER_TICK; + + /* We know we are at the head of the ready to run + * prioritized list. We must be the highest priority + * task eligible for execution. Check the next task + * in the ready to run list. If it is the same + * priority, then we need to relinquish the CPU and + * give that task a shot. + */ + + if (rtcb->flink && + rtcb->flink->sched_priority >= rtcb->sched_priority) + { + /* Just resetting the task priority to its current + * value. This this will cause the task to be + * rescheduled behind any other tasks at the same + * priority. + */ + + up_reprioritize_rtr(rtcb, rtcb->sched_priority); + } + } + } + else + { + /* Decrement the timeslice counter */ + + rtcb->timeslice--; + } + } +#endif +} + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * System Timer Hooks + * + * These are standard interfaces that are exported by the OS + * for use by the architecture specific logic + * + ************************************************************************/ + +/************************************************************************ + * Name: sched_process_timer + * + * Description: + * This function handles system timer events. + * The timer interrupt logic itself is implemented in the + * architecture specific code, but must call the following OS + * function periodically -- the calling interval must be + * MSEC_PER_TICK + * + * Inputs: + * None + * + * Return Value: + * None + * + ************************************************************************/ + +void sched_process_timer(void) +{ + /* Increment the system time (if in the link) */ + +#ifndef CONFIG_DISABLE_CLOCK +#ifdef CONFIG_HAVE_WEAKFUNCTIONS + if (clock_timer != NULL) +#endif + { + clock_timer(); + } +#endif + + /* Process watchdogs (if in the link) */ + +#ifdef CONFIG_HAVE_WEAKFUNCTIONS + if (wd_timer != NULL) +#endif + { + wd_timer(); + } + + /* Check if the currently executing task has exceeded its + * timeslice. + */ + + sched_process_timeslice(); +} diff --git a/nuttx/sched/sched_releasefiles.c b/nuttx/sched/sched_releasefiles.c new file mode 100644 index 000000000..a3ef71af4 --- /dev/null +++ b/nuttx/sched/sched_releasefiles.c @@ -0,0 +1,114 @@ +/**************************************************************************** + * sched/sched_releasefiles.c + * + * Copyright (C) 2007, 2008, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include + +#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0 + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sched_releasefiles + * + * Description: + * Release file resources attached to a TCB. This file may be called + * multiple times as a task exists. It will be called as early as possible + * to support proper closing of complex drivers that may need to wait + * on external events. + * + * Parameters: + * tcb - tcb of the new task. + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +int sched_releasefiles(_TCB *tcb) +{ + if (tcb) + { +#if CONFIG_NFILE_DESCRIPTORS > 0 + /* Free the file descriptor list */ + + if (tcb->filelist) + { + files_releaselist(tcb->filelist); + tcb->filelist = NULL; + } + +#if CONFIG_NFILE_STREAMS > 0 + /* Free the stream list */ + + if (tcb->streams) + { + lib_releaselist(tcb->streams); + tcb->streams = NULL; + } +#endif /* CONFIG_NFILE_STREAMS */ +#endif /* CONFIG_NFILE_DESCRIPTORS */ + +#if CONFIG_NSOCKET_DESCRIPTORS > 0 + /* Free the file descriptor list */ + + if (tcb->sockets) + { + net_releaselist(tcb->sockets); + tcb->sockets = NULL; + } +#endif /* CONFIG_NSOCKET_DESCRIPTORS */ + } + + return OK; +} + +#endif /* CONFIG_NFILE_DESCRIPTORS || CONFIG_NSOCKET_DESCRIPTORS */ diff --git a/nuttx/sched/sched_releasetcb.c b/nuttx/sched/sched_releasetcb.c new file mode 100644 index 000000000..21837262d --- /dev/null +++ b/nuttx/sched/sched_releasetcb.c @@ -0,0 +1,181 @@ +/************************************************************************ + * sched/sched_releasetcb.c + * + * Copyright (C) 2007, 2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include + +#include "os_internal.h" +#include "timer_internal.h" +#include "env_internal.h" + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Name: sched_releasepid + * + * Description: When a task is destroyed, this function must + * be called to make its process ID available for re-use. + ************************************************************************/ + +static void sched_releasepid(pid_t pid) +{ + int hash_ndx = PIDHASH(pid); + + /* Make any pid associated with this hash available. Note: + * no special precautions need be taken here because the + * following action is atomic + */ + + g_pidhash[hash_ndx].tcb = NULL; + g_pidhash[hash_ndx].pid = INVALID_PROCESS_ID; +} + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sched_releasetcb + * + * Description: + * Free all resources contained in a TCB + * + * Parameters: + * None + * + * Return Value: + * OK on success; ERROR on failure + * + * Assumptions: + * Interrupts are disabled. + * + ************************************************************************/ + +int sched_releasetcb(FAR _TCB *tcb) +{ + int ret = OK; + int i; + + if (tcb) + { + /* Relase any timers that the task might hold. We do this + * before release the PID because it may still be trying to + * deliver signals (although interrupts are should be + * disabled here). + */ + +#ifndef CONFIG_DISABLE_POSIX_TIMERS +#ifdef CONFIG_HAVE_WEAKFUNCTIONS + if (timer_deleteall != NULL) +#endif + { + timer_deleteall(tcb->pid); + } +#endif + + /* Release the task's process ID if one was assigned. PID + * zero is reserved for the IDLE task. The TCB of the IDLE + * task is never release so a value of zero simply means that + * the process ID was never allocated to this TCB. + */ + + if (tcb->pid) + { + sched_releasepid(tcb->pid); + } + + /* Delete the thread's stack if one has been allocated */ + +#ifndef CONFIG_CUSTOM_STACK + if (tcb->stack_alloc_ptr) + { + up_release_stack(tcb); + } +#endif + + /* Delete the tasks's allocated DSpace region (external modules only) */ + +#ifdef CONFIG_PIC + if (tcb->dspace) + { + if (tcb->dspace->crefs <= 1) + { + sched_free(tcb->dspace); + } + else + { + tcb->dspace->crefs--; + } + } +#endif + + /* Release command line arguments that were allocated for task + * start/re-start. + */ + + if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_TASK) + { + for (i = 1; i < CONFIG_MAX_TASK_ARGS+1 && tcb->argv[i]; i++) + { + sched_free((FAR void*)tcb->argv[i]); + } + } + + /* Release any allocated file structures */ + + ret = sched_releasefiles(tcb); + + /* Release environment variables */ + + (void)env_release(tcb); + + /* And, finally, release the TCB itself */ + + sched_free(tcb); + } + + return ret; +} + diff --git a/nuttx/sched/sched_removeblocked.c b/nuttx/sched/sched_removeblocked.c new file mode 100644 index 000000000..8d5a127d2 --- /dev/null +++ b/nuttx/sched/sched_removeblocked.c @@ -0,0 +1,111 @@ +/************************************************************************ + * sched/sched_removeblocked.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include + +#include "os_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sched_removeblocked + * + * Description: + * This function removes a TCB from one of the blocked state task + * lists as inferred from the task_state inside the TCB. + * + * Inputs: + * btcb - Points to the TCB that is blocked + * + * Return Value: + * None + * + * Assumptions: + * - The caller has established a critical section before + * calling this function. + * + ************************************************************************/ + +void sched_removeblocked(FAR _TCB *btcb) +{ + tstate_t task_state = btcb->task_state; + + /* Make sure the TCB is in a valid blocked state */ + + ASSERT(task_state >= FIRST_BLOCKED_STATE && + task_state <= LAST_BLOCKED_STATE); + + /* Remove the TCB from the blocked task list associated + * with this state + */ + + dq_rem((FAR dq_entry_t*)btcb, (dq_queue_t*)g_tasklisttable[task_state].list); + + /* Make sure the TCB's state corresponds to not being in + * any list + */ + + btcb->task_state = TSTATE_TASK_INVALID; +} + diff --git a/nuttx/sched/sched_removereadytorun.c b/nuttx/sched/sched_removereadytorun.c new file mode 100644 index 000000000..4982808e2 --- /dev/null +++ b/nuttx/sched/sched_removereadytorun.c @@ -0,0 +1,121 @@ +/**************************************************************************** + * shced/sched_removereadytorun.c + * + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include + +#include "os_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sched_removereadytorun + * + * Description: + * This function removes a TCB from the ready to run list. + * + * Inputs: + * rtcb - Points to the TCB that is ready-to-run + * + * Return Value: + * true if the currently active task (the head of the + * g_readytorun list) has changed. + * + * Assumptions: + * - The caller has established a critical section before calling this + * function (calling sched_lock() first is NOT a good idea -- use irqsave()). + * - The caller handles the condition that occurs if the + * the head of the g_readytorun list is changed. + * + ****************************************************************************/ + +bool sched_removereadytorun(FAR _TCB *rtcb) +{ + bool ret = false; + + /* Check if the TCB to be removed is at the head of the ready to run list. + * In this case, we are removing the currently active task. + */ + + if (!rtcb->blink) + { + /* There must always be at least one task in the list (the idle task) */ + + ASSERT(rtcb->flink != NULL); + + /* Inform the instrumentation layer that we are switching tasks */ + + sched_note_switch(rtcb, rtcb->flink); + + rtcb->flink->task_state = TSTATE_TASK_RUNNING; + ret = true; + } + + /* Remove the TCB from the ready-to-run list */ + + dq_rem((FAR dq_entry_t*)rtcb, (dq_queue_t*)&g_readytorun); + + rtcb->task_state = TSTATE_TASK_INVALID; + return ret; +} diff --git a/nuttx/sched/sched_reprioritize.c b/nuttx/sched/sched_reprioritize.c new file mode 100644 index 000000000..bd316ec75 --- /dev/null +++ b/nuttx/sched/sched_reprioritize.c @@ -0,0 +1,129 @@ +/**************************************************************************** + * sched/sched_reprioritize.c + * + * Copyright (C) 2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include + +#include "os_internal.h" + +#ifdef CONFIG_PRIORITY_INHERITANCE + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sched_reprioritize + * + * Description: + * This function sets the priority of a specified task. + * + * NOTE: Setting a task's priority to the same value has a similar effect + * to sched_yield() -- The task will be moved to after all other tasks + * with the same priority. + * + * Inputs: + * tcb - the TCB of task to reprioritize. + * sched_priority - The new task priority + * + * Return Value: + * On success, sched_setparam() returns 0 (OK). On error, -1 + * (ERROR) is returned, and errno is set appropriately. + * + * EINVAL The parameter 'param' is invalid or does not make sense for the + * current scheduling policy. + * EPERM The calling task does not have appropriate privileges. + * ESRCH The task whose ID is pid could not be found. + * + * Assumptions: + * + ****************************************************************************/ + +int sched_reprioritize(FAR _TCB *tcb, int sched_priority) +{ + /* This function is equivalent to sched_setpriority() BUT it also has the + * side effect of discarding all priority inheritance history. This is + * done only on explicit, user-initiated reprioritization. + */ + + int ret = sched_setpriority(tcb, sched_priority); + if (ret == 0) + { + /* Reset the base_priority -- the priority that the thread would return + * to once it posts the semaphore. + */ + + tcb->base_priority = (uint8_t)sched_priority; + + /* Discard any pending reprioritizations as well */ + +#if CONFIG_SEM_NNESTPRIO > 0 + tcb->npend_reprio = 0; +#endif + } + return ret; +} +#endif /* CONFIG_PRIORITY_INHERITANCE */ diff --git a/nuttx/sched/sched_rrgetinterval.c b/nuttx/sched/sched_rrgetinterval.c new file mode 100644 index 000000000..961c58ec5 --- /dev/null +++ b/nuttx/sched/sched_rrgetinterval.c @@ -0,0 +1,157 @@ +/************************************************************************ + * sched/sched_rrgetinterval.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include + +#include + +#include "os_internal.h" +#include "clock_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sched_rr_get_interval + * + * Description: + * sched_rr_get_interval() writes the timeslice interval for task + * identified by 'pid' into the timespec structure pointed to by + * 'interval.' If pid is zero, the timeslice for the calling process + * is written into 'interval. The identified process should be running + * under the SCHED_RRscheduling policy.' + * + * Inputs: + * pid - the task ID of the task. If pid is zero, the priority of the + * calling task is returned. + * interval - a structure used to return the time slice + * + * Return Value: + * On success, sched_rr_get_interval() returns OK (0). On error, + * ERROR (-1) is returned, and errno is set to: + * + * EFAULT -- Cannot copy to interval + * EINVAL Invalid pid. + * ENOSYS The system call is not yet implemented. + * ESRCH The process whose ID is pid could not be found. + * + * Assumptions: + * + ************************************************************************/ + +int sched_rr_get_interval(pid_t pid, struct timespec *interval) +{ +#if CONFIG_RR_INTERVAL > 0 + FAR _TCB *rrtcb; + + /* If pid is zero, the timeslice for the calling process is written + * into 'interval.' + */ + + if (!pid) + { + rrtcb = (FAR _TCB*)g_readytorun.head; + } + + /* Return a special error code on invalid PID */ + + else if (pid < 0) + { + set_errno(EINVAL); + return ERROR; + } + + /* Otherwise, lookup the TCB associated with this pid */ + + else + { + rrtcb = sched_gettcb(pid); + if (!rrtcb) + { + set_errno(ESRCH); + return ERROR; + } + } + + if (!interval) + { + set_errno(EFAULT); + return ERROR; + } + + /* Convert the timeslice value from ticks to timespec */ + + interval->tv_sec = CONFIG_RR_INTERVAL / MSEC_PER_SEC; + interval->tv_nsec = (CONFIG_RR_INTERVAL % MSEC_PER_SEC) * NSEC_PER_MSEC; + + return OK; +#else + set_errno(ENOSYS); + return ERROR; +#endif +} diff --git a/nuttx/sched/sched_self.c b/nuttx/sched/sched_self.c new file mode 100644 index 000000000..9517e6306 --- /dev/null +++ b/nuttx/sched/sched_self.c @@ -0,0 +1,83 @@ +/**************************************************************************** + * sched/sched_self.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include +#include "os_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sched_self + * + * Description: + * Return the current threads TCB. Basically, this function just wraps the + * head of the ready-to-run list and manages access to the TCB from outside + * of the sched/ sub-directory. + * + ****************************************************************************/ + +FAR _TCB *sched_self(void) +{ + return (FAR _TCB*)g_readytorun.head; +} + + diff --git a/nuttx/sched/sched_setparam.c b/nuttx/sched/sched_setparam.c new file mode 100644 index 000000000..6ea4e8f74 --- /dev/null +++ b/nuttx/sched/sched_setparam.c @@ -0,0 +1,156 @@ +/**************************************************************************** + * sched/sched_setparam.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include + +#include + +#include "os_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sched_setparam + * + * Description: + * This function sets the priority of a specified task. + * + * NOTE: Setting a task's priority to the same value has a similar effect + * to sched_yield() -- The task will be moved to after all other tasks + * with the same priority. + * + * Inputs: + * pid - the task ID of the task to reprioritize. If pid is zero, the + * priority of the calling task is changed. + * param - A structure whose member sched_priority is the integer priority. + * The range of valid priority numbers is from SCHED_PRIORITY_MIN + * through SCHED_PRIORITY_MAX. + * + * Return Value: + * On success, sched_setparam() returns 0 (OK). On error, -1 (ERROR) is + * returned, and errno is set appropriately. + * + * EINVAL The parameter 'param' is invalid or does not make sense for the + * current scheduling policy. + * EPERM The calling task does not have appropriate privileges. + * ESRCH The task whose ID is pid could not be found. + * + * Assumptions: + * + ****************************************************************************/ + +int sched_setparam(pid_t pid, const struct sched_param *param) +{ + FAR _TCB *rtcb; + FAR _TCB *tcb; + int ret; + + /* Verify that the requested priority is in the valid range */ + + if (!param) + { + errno = EINVAL; + return ERROR; + } + + /* Prohibit modifications to the head of the ready-to-run task + * list while adjusting the priority + */ + + sched_lock(); + + /* Check if the task to reprioritize is the calling task */ + + rtcb = (FAR _TCB*)g_readytorun.head; + if (pid == 0 || pid == rtcb->pid) + { + tcb = rtcb; + } + + /* The pid is not the calling task, we will have to search for it */ + + else + { + tcb = sched_gettcb(pid); + if (!tcb) + { + /* No task with this pid was found */ + + errno = ESRCH; + sched_unlock(); + return ERROR; + } + } + + /* Then perform the reprioritization */ + + ret = sched_reprioritize(tcb, param->sched_priority); + sched_unlock(); + return ret; +} diff --git a/nuttx/sched/sched_setpriority.c b/nuttx/sched/sched_setpriority.c new file mode 100644 index 000000000..6aa0789ea --- /dev/null +++ b/nuttx/sched/sched_setpriority.c @@ -0,0 +1,233 @@ +/**************************************************************************** + * sched/sched_setpriority.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include + +#include "os_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sched_setpriority + * + * Description: + * This function sets the priority of a specified task. + * + * NOTE: Setting a task's priority to the same value has a similar effect + * to sched_yield() -- The task will be moved to after all other tasks + * with the same priority. + * + * Inputs: + * tcb - the TCB of task to reprioritize. + * sched_priority - The new task priority + * + * Return Value: + * On success, sched_setparam() returns 0 (OK). On error, -1 (ERROR) is + * returned, and errno is set appropriately. + * + * EINVAL The parameter 'param' is invalid or does not make sense for the + * current scheduling policy. + * EPERM The calling task does not have appropriate privileges. + * ESRCH The task whose ID is pid could not be found. + * + * Assumptions: + * + ****************************************************************************/ + +int sched_setpriority(FAR _TCB *tcb, int sched_priority) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + tstate_t task_state; + irqstate_t saved_state; + + /* Verify that the requested priority is in the valid range */ + + if (sched_priority < SCHED_PRIORITY_MIN || + sched_priority > SCHED_PRIORITY_MAX) + { + errno = EINVAL; + return ERROR; + } + + /* We need to assure that there there is no interrupt activity while + * performing the following. + */ + + saved_state = irqsave(); + + /* There are four cases that must be considered: */ + + task_state = tcb->task_state; + switch (task_state) + { + /* CASE 1. The task is running or ready-to-run and a context switch + * may be caused by the re-prioritization + */ + + case TSTATE_TASK_RUNNING: + + /* A context switch will occur if the new priority of the running + * task becomes less than OR EQUAL TO the next highest priority + * ready to run task. + */ + + if (sched_priority <= tcb->flink->sched_priority) + { + /* A context switch will occur. */ + + up_reprioritize_rtr(tcb, (uint8_t)sched_priority); + } + + /* Otherwise, we can just change priority since it has no effect */ + + else + { + /* Change the task priority */ + + tcb->sched_priority = (uint8_t)sched_priority; + } + break; + + /* CASE 2. The task is running or ready-to-run and a context switch + * may be caused by the re-prioritization + */ + + case TSTATE_TASK_READYTORUN: + + /* A context switch will occur if the new priority of the ready-to + * run task is (strictly) greater than the current running task + */ + + if (sched_priority > rtcb->sched_priority) + { + /* A context switch will occur. */ + + up_reprioritize_rtr(tcb, (uint8_t)sched_priority); + } + + /* Otherwise, we can just change priority and re-schedule (since it + * have no other effect). + */ + + else + { + /* Remove the TCB from the ready-to-run task list */ + + ASSERT(!sched_removereadytorun(tcb)); + + /* Change the task priority */ + + tcb->sched_priority = (uint8_t)sched_priority; + + /* Put it back into the ready-to-run task list */ + + ASSERT(!sched_addreadytorun(tcb)); + } + break; + + /* CASE 3. The task is not in the ready to run list. Changing its + * Priority cannot effect the currently executing task. + */ + + default: + + /* CASE 3a. The task resides in a prioritized list. */ + + if (g_tasklisttable[task_state].prioritized) + { + /* Remove the TCB from the prioritized task list */ + + dq_rem((FAR dq_entry_t*)tcb, (FAR dq_queue_t*)g_tasklisttable[task_state].list); + + /* Change the task priority */ + + tcb->sched_priority = (uint8_t)sched_priority; + + /* Put it back into the prioritized list at the correct + * position + */ + + sched_addprioritized(tcb, (FAR dq_queue_t*)g_tasklisttable[task_state].list); + } + + /* CASE 3b. The task resides in a non-prioritized list. */ + + else + { + /* Just change the task's priority */ + + tcb->sched_priority = (uint8_t)sched_priority; + } + break; + } + + irqrestore(saved_state); + return OK; +} diff --git a/nuttx/sched/sched_setscheduler.c b/nuttx/sched/sched_setscheduler.c new file mode 100644 index 000000000..7f7f345b4 --- /dev/null +++ b/nuttx/sched/sched_setscheduler.c @@ -0,0 +1,187 @@ +/**************************************************************************** + * sched/sched_setscheduler.c + * + * Copyright (C) 2007, 2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include + +#include + +#include "os_internal.h" +#include "clock_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name:sched_setscheduler + * + * Description: + * sched_setscheduler() sets both the scheduling policy and the priority + * for the task identified by pid. If pid equals zero, the scheduler of + * the calling task will be set. The parameter 'param' holds the priority + * of the thread under the new policy. + * + * Inputs: + * pid - the task ID of the task to modify. If pid is zero, the calling + * task is modified. + * policy - Scheduling policy requested (either SCHED_FIFO or SCHED_RR) + * param - A structure whose member sched_priority is the new priority. + * The range of valid priority numbers is from SCHED_PRIORITY_MIN + * through SCHED_PRIORITY_MAX. + * + * Return Value: + * On success, sched_setscheduler() returns OK (zero). On error, ERROR + * (-1) is returned, and errno is set appropriately: + * + * EINVAL The scheduling policy is not one of the recognized policies. + * ESRCH The task whose ID is pid could not be found. + * + * Assumptions: + * + ****************************************************************************/ + +int sched_setscheduler(pid_t pid, int policy, + const struct sched_param *param) +{ + FAR _TCB *tcb; +#if CONFIG_RR_INTERVAL > 0 + irqstate_t saved_state; +#endif + int ret; + + /* Check for supported scheduling policy */ + +#if CONFIG_RR_INTERVAL > 0 + if (policy != SCHED_FIFO && policy != SCHED_RR) +#else + if (policy != SCHED_FIFO) +#endif + { + errno = EINVAL; + return ERROR; + } + + /* Check if the task to modify the calling task */ + + if (pid == 0 ) + { + pid = getpid(); + } + + /* Verify that the pid corresponds to a real task */ + + tcb = sched_gettcb(pid); + if (!tcb) + { + errno = ESRCH; + return ERROR; + } + + /* Prohibit any context switches while we muck with priority and scheduler + * settings. + */ + + sched_lock(); + +#if CONFIG_RR_INTERVAL > 0 + /* Further, disable timer interrupts while we set up scheduling policy. */ + + saved_state = irqsave(); + if (policy == SCHED_RR) + { + /* Set round robin scheduling */ + + tcb->flags |= TCB_FLAG_ROUND_ROBIN; + tcb->timeslice = CONFIG_RR_INTERVAL / MSEC_PER_TICK; + } + else + { + /* Set FIFO scheduling */ + + tcb->flags &= ~TCB_FLAG_ROUND_ROBIN; + tcb->timeslice = 0; + } + + irqrestore(saved_state); +#endif + + /* Set the new priority */ + + ret = sched_reprioritize(tcb, param->sched_priority); + sched_unlock(); + + if (ret != OK) + { + return ERROR; + } + else + { + return OK; + } +} + diff --git a/nuttx/sched/sched_setupidlefiles.c b/nuttx/sched/sched_setupidlefiles.c new file mode 100644 index 000000000..ae814e1a6 --- /dev/null +++ b/nuttx/sched/sched_setupidlefiles.c @@ -0,0 +1,148 @@ +/**************************************************************************** + * sched/sched_setupidlefiles.c + * + * Copyright (C) 2007-2010, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "os_internal.h" + +#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0 + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sched_setupidlefiles + * + * Description: + * Configure the idle thread's TCB. + * + * Parameters: + * tcb - tcb of the idle task. + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +int sched_setupidlefiles(FAR _TCB *tcb) +{ +#if CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_DEV_CONSOLE) + int fd; +#endif + + /* Allocate file descriptors for the TCB */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 + tcb->filelist = files_alloclist(); + if (!tcb->filelist) + { + return -ENOMEM; + } +#endif + + /* Allocate socket descriptors for the TCB */ + +#if CONFIG_NSOCKET_DESCRIPTORS > 0 + tcb->sockets = net_alloclist(); + if (!tcb->sockets) + { + return -ENOMEM; + } +#endif + + /* Open stdin, dup to get stdout and stderr. This should always + * be the first file opened and, hence, should always get file + * descriptor 0. + */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_DEV_CONSOLE) + fd = open("/dev/console", O_RDWR); + if (fd == 0) + { + /* Successfully opened /dev/console as stdin (fd == 0) */ + + (void)file_dup2(0, 1); + (void)file_dup2(0, 2); + } + else + { + /* We failed to open /dev/console OR for some reason, we opened + * it and got some file descriptor other than 0. + */ + + if (fd > 0) + { + slldbg("Open /dev/console fd: %d\n", fd); + (void)close(fd); + } + else + { + slldbg("Failed to open /dev/console: %d\n", errno); + } + return -ENFILE; + } +#endif + + /* Allocate file/socket streams for the TCB */ + +#if CONFIG_NFILE_STREAMS > 0 + return sched_setupstreams(tcb); +#else + return OK; +#endif +} + +#endif /* CONFIG_NFILE_DESCRIPTORS || CONFIG_NSOCKET_DESCRIPTORS */ diff --git a/nuttx/sched/sched_setuppthreadfiles.c b/nuttx/sched/sched_setuppthreadfiles.c new file mode 100644 index 000000000..648d9273e --- /dev/null +++ b/nuttx/sched/sched_setuppthreadfiles.c @@ -0,0 +1,108 @@ +/**************************************************************************** + * sched_setuppthreadfiles.c + * + * Copyright (C) 2007, 2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include + +#include +#include +#include + +#include "os_internal.h" + +#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0 + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sched_setuppthreadfiles + * + * Description: + * Configure a newly allocated TCB so that it will inherit file + * descriptors and streams from the parent pthread. + * + * Parameters: + * tcb - tcb of the new task. + * + * Return Value: + * OK (if an error were returned, it would need to be a non-negated + * errno value). + * + * Assumptions: + * + ****************************************************************************/ + +int sched_setuppthreadfiles(FAR _TCB *tcb) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + +#if CONFIG_NFILE_DESCRIPTORS > 0 + /* The child thread inherits the parent file descriptors */ + + tcb->filelist = rtcb->filelist; + files_addreflist(tcb->filelist); + +#endif /* CONFIG_NFILE_DESCRIPTORS */ + +#if CONFIG_NSOCKET_DESCRIPTORS > 0 + /* The child thread inherits the parent socket descriptors */ + + tcb->sockets = rtcb->sockets; + net_addreflist(tcb->sockets); + +#endif /* CONFIG_NSOCKET_DESCRIPTORS */ + +#if CONFIG_NFILE_STREAMS > 0 + /* The child thread inherits the parent streams */ + + tcb->streams = rtcb->streams; + lib_addreflist(tcb->streams); + +#endif /* CONFIG_NFILE_STREAMS */ + return OK; +} + +#endif /* CONFIG_NFILE_DESCRIPTORS || CONFIG_NSOCKET_DESCRIPTORS */ diff --git a/nuttx/sched/sched_setupstreams.c b/nuttx/sched/sched_setupstreams.c new file mode 100644 index 000000000..22895b047 --- /dev/null +++ b/nuttx/sched/sched_setupstreams.c @@ -0,0 +1,98 @@ +/**************************************************************************** + * sched_setupstreams.c + * + * Copyright (C) 2007-2008, 2010-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include + +#include +#include +#include + +/* Make sure that there are file or socket descriptors in the system and + * that some number of streams have been configured. + */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0 +#if CONFIG_NFILE_STREAMS > 0 + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sched_setupstreams + * + * Description: + * Setup streams data structures that may be used for standard C buffered + * I/O with underlying socket or file desciptors + * + ****************************************************************************/ + +int sched_setupstreams(FAR _TCB *tcb) +{ + /* Allocate file streams for the TCB */ + + tcb->streams = lib_alloclist(); + if (tcb->streams) + { + /* fdopen to get the stdin, stdout and stderr streams. + * The following logic depends on the fact that the library + * layer will allocate FILEs in order. + * + * fd = 0 is stdin (read-only) + * fd = 1 is stdout (write-only, append) + * fd = 2 is stderr (write-only, append) + */ + + (void)fs_fdopen(0, O_RDONLY, tcb); + (void)fs_fdopen(1, O_WROK|O_CREAT, tcb); + (void)fs_fdopen(2, O_WROK|O_CREAT, tcb); + } + + return OK; +} + +#endif /* CONFIG_NFILE_STREAMS > 0 */ +#endif /* CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0*/ diff --git a/nuttx/sched/sched_setuptaskfiles.c b/nuttx/sched/sched_setuptaskfiles.c new file mode 100644 index 000000000..fe0b14143 --- /dev/null +++ b/nuttx/sched/sched_setuptaskfiles.c @@ -0,0 +1,248 @@ +/**************************************************************************** + * sched/sched_setuptaskfiles.c + * + * Copyright (C) 2007-2008, 2010, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include + +#include +#include + +#include "os_internal.h" + +#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0 + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Determine how many file descriptors to clone. If CONFIG_FDCLONE_DISABLE + * is set, no file descriptors will be cloned. If CONFIG_FDCLONE_STDIO is + * set, only the first three descriptors (stdin, stdout, and stderr) will + * be cloned. Otherwise all file descriptors will be cloned. + */ + +#if defined(CONFIG_FDCLONE_STDIO) && CONFIG_NFILE_DESCRIPTORS > 3 +# define NFDS_TOCLONE 3 +#else +# define NFDS_TOCLONE CONFIG_NFILE_DESCRIPTORS +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sched_dupfiles + * + * Description: + * Duplicate parent task's file descriptors. + * + * Input Parameters: + * tcb - tcb of the new task. + * + * Return Value: + * None + * + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_FDCLONE_DISABLE) +static inline void sched_dupfiles(FAR _TCB *tcb) +{ + /* The parent task is the one at the head of the ready-to-run list */ + + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + FAR struct file *parent; + FAR struct file *child; + int i; + + /* Duplicate the file descriptors. This will be either all of the + * file descriptors or just the first three (stdin, stdout, and stderr) + * if CONFIG_FDCLONE_STDIO is defined. NFSDS_TOCLONE is set + * accordingly above. + */ + + if (rtcb->filelist) + { + /* Get pointers to the parent and child task file lists */ + + parent = rtcb->filelist->fl_files; + child = tcb->filelist->fl_files; + + /* Check each file in the parent file list */ + + for (i = 0; i < NFDS_TOCLONE; i++) + { + /* Check if this file is opened by the parent. We can tell if + * if the file is open because it contain a reference to a non-NULL + * i-node structure. + */ + + if (parent[i].f_inode) + { + /* Yes... duplicate it for the child */ + + (void)files_dup(&parent[i], &child[i]); + } + } + } +} +#else /* CONFIG_NFILE_DESCRIPTORS && !CONFIG_FDCLONE_DISABLE */ +# define sched_dupfiles(tcb) +#endif /* CONFIG_NFILE_DESCRIPTORS && !CONFIG_FDCLONE_DISABLE */ + +/**************************************************************************** + * Name: sched_dupsockets + * + * Description: + * Duplicate the parent task's socket descriptors. + * + * Input Parameters: + * tcb - tcb of the new task. + * + * Return Value: + * None + * + ****************************************************************************/ + +#if CONFIG_NSOCKET_DESCRIPTORS > 0 && !defined(CONFIG_SDCLONE_DISABLE) +static inline void sched_dupsockets(FAR _TCB *tcb) +{ + /* The parent task is the one at the head of the ready-to-run list */ + + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + FAR struct socket *parent; + FAR struct socket *child; + int i; + + /* Duplicate the socket descriptors of all sockets opened by the parent + * task. + */ + + if (rtcb->sockets) + { + /* Get pointers to the parent and child task socket lists */ + + parent = rtcb->sockets->sl_sockets; + child = tcb->sockets->sl_sockets; + + /* Check each socket in the parent socket list */ + + for (i = 0; i < CONFIG_NSOCKET_DESCRIPTORS; i++) + { + /* Check if this parent socket is allocated. We can tell if the + * socket is allocated because it will have a positive, non-zero + * reference count. + */ + + if (parent[i].s_crefs > 0) + { + /* Yes... duplicate it for the child */ + + (void)net_clone(&parent[i], &child[i]); + } + } + } +} +#else /* CONFIG_NSOCKET_DESCRIPTORS && !CONFIG_SDCLONE_DISABLE */ +# define sched_dupsockets(tcb) +#endif /* CONFIG_NSOCKET_DESCRIPTORS && !CONFIG_SDCLONE_DISABLE */ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sched_setuptaskfiles + * + * Description: + * Configure a newly allocated TCB so that it will inherit + * file descriptors and streams from the parent task. + * + * Parameters: + * tcb - tcb of the new task. + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +int sched_setuptaskfiles(FAR _TCB *tcb) +{ + /* Allocate file descriptors for the TCB */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 + tcb->filelist = files_alloclist(); + if (!tcb->filelist) + { + return -ENOMEM; + } +#endif + + /* Allocate socket descriptors for the TCB */ + +#if CONFIG_NSOCKET_DESCRIPTORS > 0 + tcb->sockets = net_alloclist(); + if (!tcb->sockets) + { + return -ENOMEM; + } +#endif + + /* Duplicate the parent task's file descriptors */ + + sched_dupfiles(tcb); + + /* Duplicate the parent task's socket descriptors */ + + sched_dupsockets(tcb); + + /* Allocate file/socket streams for the new TCB */ + +#if CONFIG_NFILE_STREAMS > 0 + return sched_setupstreams(tcb); +#else + return OK; +#endif +} + +#endif /* CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0*/ diff --git a/nuttx/sched/sched_unlock.c b/nuttx/sched/sched_unlock.c new file mode 100644 index 000000000..9a52e8358 --- /dev/null +++ b/nuttx/sched/sched_unlock.c @@ -0,0 +1,130 @@ +/************************************************************************ + * sched/sched_unlock.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include + +#include "os_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/************************************************************************ + * Private Functionss + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sched_unlock + * + * Description: + * This function decrements the preemption lock count. Typically this + * is paired with sched_lock() and concludes a critical section of + * code. Preemption will not be unlocked until sched_unlock() has + * been called as many times as sched_lock(). When the lockcount is + * decremented to zero, any tasks that were eligible to preempt the + * current task will execute. + * + ************************************************************************/ + +int sched_unlock(void) +{ + _TCB *rtcb = (_TCB*)g_readytorun.head; + + /* Check for some special cases: (1) rtcb may be NULL only during + * early boot-up phases, and (2) sched_unlock() should have no + * effect if called from the interrupt level. + */ + + if (rtcb && !up_interrupt_context()) + { + /* Prevent context switches throughout the following */ + + irqstate_t flags = irqsave(); + + /* Decrement the preemption lock counter */ + + if (rtcb->lockcount) + { + rtcb->lockcount--; + } + + /* Check if the lock counter has decremented to zero. If so, + * then pre-emption has been re-enabled. + */ + + if (rtcb->lockcount <= 0) + { + rtcb->lockcount = 0; + + /* Release any ready-to-run tasks that have collected in + * g_pendingtasks. + */ + + if (g_pendingtasks.head) + { + up_release_pending(); + } + } + + irqrestore(flags); + } + return OK; +} diff --git a/nuttx/sched/sched_verifytcb.c b/nuttx/sched/sched_verifytcb.c new file mode 100644 index 000000000..bcf097a5c --- /dev/null +++ b/nuttx/sched/sched_verifytcb.c @@ -0,0 +1,86 @@ +/**************************************************************************** + * sched/ched_verifytcb.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include + +#include "os_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sched_verifytcb + * + * Description: + * Return true if the tcb refers to an active task; false if it is a stale + * TCB handle. + * + ****************************************************************************/ + +bool sched_verifytcb(FAR _TCB *tcb) +{ + /* Return true if the PID hashes to this TCB. */ + + return tcb == g_pidhash[PIDHASH(tcb->pid)].tcb; +} + diff --git a/nuttx/sched/sched_waitpid.c b/nuttx/sched/sched_waitpid.c new file mode 100644 index 000000000..692ef6410 --- /dev/null +++ b/nuttx/sched/sched_waitpid.c @@ -0,0 +1,248 @@ +/***************************************************************************** + * sched/sched_waitpid.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include + +#include + +#include "os_internal.h" + +#ifdef CONFIG_SCHED_WAITPID /* Experimental */ + +/***************************************************************************** + * Private Functions + *****************************************************************************/ + +/***************************************************************************** + * Public Functions + *****************************************************************************/ + +/***************************************************************************** + * Name: sched_waitpid + * + * Description: + * + * The waitpid() functions will obtain status information pertaining to one + * of the caller's child processes. The waitpid() function will suspend + * execution of the calling thread until status information for one of the + * terminated child processes of the calling process is available, or until + * delivery of a signal whose action is either to execute a signal-catching + * function or to terminate the process. If more than one thread is suspended + * in waitpid() awaiting termination of the same process, exactly one thread + * will return the process status at the time of the target process + * termination. If status information is available prior to the call to + * waitpid(), return will be immediate. + * + * The pid argument specifies a set of child processes for which status is + * requested. The waitpid() function will only return the status of a child + * process from this set: + * + * - If pid is equal to (pid_t)-1, status is requested for any child process. + * In this respect, waitpid() is then equivalent to wait(). + * - If pid is greater than 0, it specifies the process ID of a single child + * process for which status is requested. + * - If pid is 0, status is requested for any child process whose process + * group ID is equal to that of the calling process. + * - If pid is less than (pid_t)-1, status is requested for any child process + * whose process group ID is equal to the absolute value of pid. + * + * The options argument is constructed from the bitwise-inclusive OR of zero + * or more of the following flags, defined in the header: + * + * WCONTINUED - The waitpid() function will report the status of any + * continued child process specified by pid whose status has not been + * reported since it continued from a job control stop. + * WNOHANG - The waitpid() function will not suspend execution of the + * calling thread if status is not immediately available for one of the + * child processes specified by pid. + * WUNTRACED - The status of any child processes specified by pid that are + * stopped, and whose status has not yet been reported since they stopped, + * will also be reported to the requesting process. + * + * If the calling process has SA_NOCLDWAIT set or has SIGCHLD set to + * SIG_IGN, and the process has no unwaited-for children that were + * transformed into zombie processes, the calling thread will block until all + * of the children of the process containing the calling thread terminate, and + * waitpid() will fail and set errno to ECHILD. + * + * If waitpid() returns because the status of a child process is available, + * these functions will return a value equal to the process ID of the child + * process. In this case, if the value of the argument stat_loc is not a + * null pointer, information will be stored in the location pointed to by + * stat_loc. The value stored at the location pointed to by stat_loc will be + * 0 if and only if the status returned is from a terminated child process + * that terminated by one of the following means: + * + * 1. The process returned 0 from main(). + * 2. The process called _exit() or exit() with a status argument of 0. + * 3. The process was terminated because the last thread in the process terminated. + * + * Regardless of its value, this information may be interpreted using the + * following macros, which are defined in and evaluate to + * integral expressions; the stat_val argument is the integer value pointed + * to by stat_loc. + * + * WIFEXITED(stat_val) - Evaluates to a non-zero value if status was + * returned for a child process that terminated normally. + * WEXITSTATUS(stat_val) - If the value of WIFEXITED(stat_val) is non-zero, + * this macro evaluates to the low-order 8 bits of the status argument + * that the child process passed to _exit() or exit(), or the value the + * child process returned from main(). + * WIFSIGNALED(stat_val) - Evaluates to a non-zero value if status was + * returned for a child process that terminated due to the receipt of a + * signal that was not caught (see ). + * WTERMSIG(stat_val) - If the value of WIFSIGNALED(stat_val) is non-zero, + * this macro evaluates to the number of the signal that caused the + * termination of the child process. + * WIFSTOPPED(stat_val) - Evaluates to a non-zero value if status was + * returned for a child process that is currently stopped. + * WSTOPSIG(stat_val) - If the value of WIFSTOPPED(stat_val) is non-zero, + * this macro evaluates to the number of the signal that caused the child + * process to stop. + * WIFCONTINUED(stat_val) - Evaluates to a non-zero value if status was + * returned for a child process that has continued from a job control stop. + * + * Parameters: + * pid - The task ID of the thread to waid for + * stat_loc - The location to return the exit status + * options - ignored + * + * Return Value: + * If waitpid() returns because the status of a child process is available, + * it will return a value equal to the process ID of the child process for + * which status is reported. + * + * If waitpid() returns due to the delivery of a signal to the calling + * process, -1 will be returned and errno set to EINTR. + * + * If waitpid() was invoked with WNOHANG set in options, it has at least + * one child process specified by pid for which status is not available, and + * status is not available for any process specified by pid, 0 is returned. + * + * Otherwise, (pid_t)-1 will be returned, and errno set to indicate the error: + * + * ECHILD - The process specified by pid does not exist or is not a child of + * the calling process, or the process group specified by pid does not exist + * or does not have any member process that is a child of the calling process. + * EINTR - The function was interrupted by a signal. The value of the location + * pointed to by stat_loc is undefined. + * EINVAL - The options argument is not valid. + * + * Assumptions: + * + *****************************************************************************/ + +/***************************************************************************/ +/* NOTE: This is a partially functional, experimental version of waitpid() */ +/***************************************************************************/ + +pid_t waitpid(pid_t pid, int *stat_loc, int options) +{ + _TCB *tcb; + bool mystat; + int err; + int ret; + + /* Disable pre-emption so that nothing changes in the following tests */ + + sched_lock(); + tcb = sched_gettcb(pid); + if (!tcb) + { + err = ECHILD; + goto errout_with_errno; + } + + /* None of the options are supported */ + +#ifdef CONFIG_DEBUG + if (options != 0) + { + err = ENOSYS; + goto errout_with_errno; + } +#endif + + /* "If more than one thread is suspended in waitpid() awaiting termination of + * the same process, exactly one thread will return the process status at the + * time of the target process termination." Hmmm.. what do we return to the + * others? + */ + + if (stat_loc != NULL && tcb->stat_loc == NULL) + { + tcb->stat_loc = stat_loc; + mystat = true; + } + + /* Then wait for the task to exit */ + + ret = sem_wait(&tcb->exitsem); + if (ret < 0) + { + /* Unlock pre-emption and return the ERROR (sem_wait has already set + * the errno). Handle the awkward case of whether or not we need to + * nullify the stat_loc value. + */ + + if (mystat) + { + tcb->stat_loc = NULL; + } + + goto errout; + } + + /* On success, return the PID */ + + sched_unlock(); + return pid; + +errout_with_errno: + set_errno(err); +errout: + sched_unlock(); + return ERROR; +} + +#endif /* CONFIG_SCHED_WAITPID */ diff --git a/nuttx/sched/sched_yield.c b/nuttx/sched/sched_yield.c new file mode 100644 index 000000000..b2e6493d0 --- /dev/null +++ b/nuttx/sched/sched_yield.c @@ -0,0 +1,101 @@ +/**************************************************************************** + * sched/sched_yield.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include + +#include "os_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sched_yield + * + * Description: + * This function forces the calling task to give up the CPU (only to other + * tasks at the same priority). + * + * Inputs: + * None + * + * Return Value: + * 0 (OK) or -1 (ERROR) (errno is not set) + * + * Assumptions: + * + ****************************************************************************/ + +int sched_yield(void) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + + /* This equivalent to just resetting the task priority to its current value + * since this will cause the task to be rescheduled behind any other tasks + * at the same priority. + */ + + return sched_setpriority(rtcb, rtcb->sched_priority); +} diff --git a/nuttx/sched/sem_close.c b/nuttx/sched/sem_close.c new file mode 100644 index 000000000..169fc0448 --- /dev/null +++ b/nuttx/sched/sem_close.c @@ -0,0 +1,140 @@ +/**************************************************************************** + * sched/sem_close.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include + +#include "os_internal.h" +#include "sem_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sem_close + * + * Description: + * This function is called to indicate that the calling task is finished + * with the specified named semaphore, 'sem'. The sem_close() deallocates + * any system resources allocated by the system for this named semaphore. + * + * If the semaphore has not been removed with a call to sem_unlink(), then + * sem_close() has no effect on the named semaphore. However, when the + * named semaphore has been fully unlinked, the semaphore will vanish when + * the last task closes it. + * + * Parameters: + * sem - semaphore descriptor + * + * Return Value: + * 0 (OK), or -1 (ERROR) if unsuccessful. + * + * Assumptions: + * - Care must be taken to avoid risking the deletion of a semaphore that + * another calling task has already locked. + * - sem_close must not be called for an un-named semaphore + * + ****************************************************************************/ + +int sem_close(FAR sem_t *sem) +{ + FAR nsem_t *psem; + int ret = ERROR; + + /* Verify the inputs */ + + if (sem) + { + sched_lock(); + + /* Search the list of named semaphores */ + + for (psem = (FAR nsem_t*)g_nsems.head; + ((psem) && (sem != &psem->sem)); + psem = psem->flink); + + /* Check if we found it */ + + if (psem) + { + /* Decrement the count of sem_open connections to this semaphore */ + + if (psem->nconnect) psem->nconnect--; + + /* If the semaphore is no long connected to any processes AND the + * semaphore was previously unlinked, then deallocate it. + */ + + if (!psem->nconnect && psem->unlinked) + { + dq_rem((FAR dq_entry_t*)psem, &g_nsems); + sched_free(psem); + } + ret = OK; + } + + sched_unlock(); + } + + return ret; +} diff --git a/nuttx/sched/sem_destroy.c b/nuttx/sched/sem_destroy.c new file mode 100644 index 000000000..90a2b95ef --- /dev/null +++ b/nuttx/sched/sem_destroy.c @@ -0,0 +1,126 @@ +/**************************************************************************** + * lib/semaphore/sem_destroy.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include + +#include "sem_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sem_destroy + * + * Description: + * This function is used to destroy the un-named semaphore indicated by + * 'sem'. Only a semaphore that was created using sem_init() may be + * destroyed using sem_destroy(); the effect of calling sem_destroy() with + * a named semaphore is undefined. The effect of subsequent use of the + * semaphore sem is undefined until sem is re-initialized by another call + * to sem_init(). + * + * The effect of destroying a semaphore upon which other processes are + * currently blocked is undefined. + * + * Parameters: + * sem - Semaphore to be destroyed. + * + * Return Value: + * 0 (OK), or -1 (ERROR) if unsuccessful. + * + * Assumptions: + * + ****************************************************************************/ + +int sem_destroy (FAR sem_t *sem) +{ + /* Assure a valid semaphore is specified */ + + if (sem) + { + /* There is really no particular action that we need + * take to destroy a semaphore. We will just reset + * the count to some reasonable value (1) and release + * ownership. + * + * Check if other threads are waiting on the semaphore. + * In this case, the behavior is undefined. We will: + * leave the count unchanged but still return OK. + */ + + if (sem->semcount >= 0) + { + sem->semcount = 1; + } + + /* Release holders of the semaphore */ + + sem_destroyholder(sem); + return OK; + } + else + { + errno = -EINVAL; + return ERROR; + } +} diff --git a/nuttx/sched/sem_findnamed.c b/nuttx/sched/sem_findnamed.c new file mode 100644 index 000000000..bcba47a8a --- /dev/null +++ b/nuttx/sched/sem_findnamed.c @@ -0,0 +1,100 @@ +/************************************************************************ + * sem_findnamed.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include + +#include "sem_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sem_findnamed + * + * Description: + * Search the g_nsems list to find the semaphore with the matching name. + * + * Parameters: + * name - semaphore name + * + * Return Value: + * Pointer to the semaphore or NULL if not found + * + ************************************************************************/ + +FAR nsem_t *sem_findnamed(const char *name) +{ + FAR nsem_t *psem; + + /* Search the list of named semaphores */ + + for (psem = (FAR nsem_t*)g_nsems.head; (psem); psem = psem->flink) + { + if (!strcmp(name, psem->name)) + { + break; + } + } + + return(psem); +} + diff --git a/nuttx/sched/sem_holder.c b/nuttx/sched/sem_holder.c new file mode 100644 index 000000000..c850a3b5a --- /dev/null +++ b/nuttx/sched/sem_holder.c @@ -0,0 +1,1055 @@ +/**************************************************************************** + * sched/sem_holder.c + * + * Copyright (C) 2009-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include + +#include "os_internal.h" +#include "sem_internal.h" + +#ifdef CONFIG_PRIORITY_INHERITANCE + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +#ifndef CONFIG_SEM_PREALLOCHOLDERS +# define CONFIG_SEM_PREALLOCHOLDERS 0 +#endif + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +typedef int (*holderhandler_t)(FAR struct semholder_s *pholder, + FAR sem_t *sem, FAR void *arg); + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/* Preallocated holder structures */ + +#if CONFIG_SEM_PREALLOCHOLDERS > 0 +static struct semholder_s g_holderalloc[CONFIG_SEM_PREALLOCHOLDERS]; +static FAR struct semholder_s *g_freeholders; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sem_allocholder + ****************************************************************************/ + +static inline FAR struct semholder_s *sem_allocholder(sem_t *sem) +{ + FAR struct semholder_s *pholder; + + /* Check if the "built-in" holder is being used. We have this built-in + * holder to optimize for the simplest case where semaphores are only + * used to implement mutexes. + */ + +#if CONFIG_SEM_PREALLOCHOLDERS > 0 + pholder = g_freeholders; + if (pholder) + { + /* Remove the holder from the free list an put it into the semaphore's holder list */ + + g_freeholders = pholder->flink; + pholder->flink = sem->hhead; + sem->hhead = pholder; + + /* Make sure the initial count is zero */ + + pholder->counts = 0; + } +#else + if (!sem->holder.htcb) + { + pholder = &sem->holder; + pholder->counts = 0; + } +#endif + else + { + sdbg("Insufficient pre-allocated holders\n"); + pholder = NULL; + } + + return pholder; +} + +/**************************************************************************** + * Name: sem_findholder + ****************************************************************************/ + +static FAR struct semholder_s *sem_findholder(sem_t *sem, FAR _TCB *htcb) +{ + FAR struct semholder_s *pholder; + + /* Try to find the holder in the list of holders associated with this semaphore */ + +#if CONFIG_SEM_PREALLOCHOLDERS > 0 + for (pholder = sem->hhead; pholder; pholder = pholder->flink) +#else + pholder = &sem->holder; +#endif + { + if (pholder->htcb == htcb) + { + /* Got it! */ + + return pholder; + } + } + + /* The holder does not appear in the list */ + + return NULL; +} + +/**************************************************************************** + * Name: sem_findorallocateholder + ****************************************************************************/ + +static inline FAR struct semholder_s *sem_findorallocateholder(sem_t *sem, FAR _TCB *htcb) +{ + FAR struct semholder_s *pholder = sem_findholder(sem, htcb); + if (!pholder) + { + pholder = sem_allocholder(sem); + } + + return pholder; +} + +/**************************************************************************** + * Name: sem_freeholder + ****************************************************************************/ + +static inline void sem_freeholder(sem_t *sem, FAR struct semholder_s *pholder) +{ +#if CONFIG_SEM_PREALLOCHOLDERS > 0 + FAR struct semholder_s *curr; + FAR struct semholder_s *prev; +#endif + + /* Release the holder and counts */ + + pholder->htcb = NULL; + pholder->counts = 0; + +#if CONFIG_SEM_PREALLOCHOLDERS > 0 + /* Search the list for the matching holder */ + + for (prev = NULL, curr = sem->hhead; + curr && curr != pholder; + prev = curr, curr = curr->flink); + + if (curr) + { + /* Remove the holder from the list */ + + if (prev) + { + prev->flink = pholder->flink; + } + else + { + sem->hhead = pholder->flink; + } + + /* And put it in the free list */ + + pholder->flink = g_freeholders; + g_freeholders = pholder; + } +#endif +} + +/**************************************************************************** + * Name: sem_foreachholder + ****************************************************************************/ + +static int sem_foreachholder(FAR sem_t *sem, holderhandler_t handler, FAR void *arg) +{ + FAR struct semholder_s *pholder; +#if CONFIG_SEM_PREALLOCHOLDERS > 0 + FAR struct semholder_s *next; +#endif + int ret = 0; + +#if CONFIG_SEM_PREALLOCHOLDERS > 0 + for (pholder = sem->hhead; pholder && ret == 0; pholder = next) +#else + pholder = &sem->holder; +#endif + { +#if CONFIG_SEM_PREALLOCHOLDERS > 0 + /* In case this holder gets deleted */ + + next = pholder->flink; +#endif + /* The initial "built-in" container may hold a NULL holder */ + + if (pholder->htcb) + { + /* Call the handler */ + + ret = handler(pholder, sem, arg); + } + } + + return ret; +} + +/**************************************************************************** + * Name: sem_recoverholders + ****************************************************************************/ + +#if CONFIG_SEM_PREALLOCHOLDERS > 0 +static int sem_recoverholders(FAR struct semholder_s *pholder, FAR sem_t *sem, FAR void *arg) +{ + sem_freeholder(sem, pholder); + return 0; +} +#endif + +/**************************************************************************** + * Name: sem_boostholderprio + ****************************************************************************/ + +static int sem_boostholderprio(FAR struct semholder_s *pholder, + FAR sem_t *sem, FAR void *arg) +{ + FAR _TCB *htcb = (FAR _TCB *)pholder->htcb; + FAR _TCB *rtcb = (FAR _TCB*)arg; + + /* Make sure that the holder thread is still active. If it exited without + * releasing its counts, then that would be a bad thing. But we can take no + * real action because we don't know know that the program is doing. Perhaps + * its plan is to kill a thread, then destroy the semaphore. + */ + + if (!sched_verifytcb(htcb)) + { + sdbg("TCB 0x%08x is a stale handle, counts lost\n", htcb); + sem_freeholder(sem, pholder); + } + +#if CONFIG_SEM_NNESTPRIO > 0 + + /* If the priority of the thread that is waiting for a count is greater than + * the base priority of the thread holding a count, then we may need to + * adjust the holder's priority now or later to that priority. + */ + + else if (rtcb->sched_priority > htcb->base_priority) + { + /* If the new priority is greater than the current, possibly already + * boosted priority of the holder thread, then we will have to raise + * the holder's priority now. + */ + + if (rtcb->sched_priority > htcb->sched_priority) + { + /* If the current priority of holder thread has already been + * boosted, then add the boost priority to the list of restoration + * priorities. When the higher priority waiter thread gets its + * count, then we need to revert the holder thread to this saved + * priority (not to its base priority). + */ + + if (htcb->sched_priority > htcb->base_priority) + { + /* Save the current, boosted priority of the holder thread. */ + + if (htcb->npend_reprio < CONFIG_SEM_NNESTPRIO) + { + htcb->pend_reprios[htcb->npend_reprio] = htcb->sched_priority; + htcb->npend_reprio++; + } + else + { + sdbg("CONFIG_SEM_NNESTPRIO exceeded\n"); + } + } + + /* Raise the priority of the thread holding of the semaphore. + * This cannot cause a context switch because we have preemption + * disabled. The holder thread may be marked "pending" and the + * switch may occur during up_block_task() processing. + */ + + (void)sched_setpriority(htcb, rtcb->sched_priority); + } + else + { + /* The new priority is above the base priority of the holder, + * but not as high as its current working priority. Just put it + * in the list of pending restoration priorities so that when the + * higher priority thread gets its count, we can revert to this + * saved priority and not to the base priority. + */ + + htcb->pend_reprios[htcb->npend_reprio] = rtcb->sched_priority; + htcb->npend_reprio++; + } + } + +#else + /* If the priority of the thread that is waiting for a count is less than + * of equal to the priority of the thread holding a count, then do nothing + * because the thread is already running at a sufficient priority. + */ + + else if (rtcb->sched_priority > htcb->sched_priority) + { + /* Raise the priority of the holder of the semaphore. This + * cannot cause a context switch because we have preemption + * disabled. The task will be marked "pending" and the switch + * will occur during up_block_task() processing. + */ + + (void)sched_setpriority(htcb, rtcb->sched_priority); + } +#endif + + return 0; +} + +/**************************************************************************** + * Name: sem_verifyholder + ****************************************************************************/ + +#ifdef CONFIG_DEBUG +static int sem_verifyholder(FAR struct semholder_s *pholder, FAR sem_t *sem, FAR void *arg) +{ +#if 0 // Need to revisit this, but these assumptions seem to be untrue -- OR there is a bug??? + FAR _TCB *htcb = (FAR _TCB *)pholder->htcb; + + /* Called after a semaphore has been released (incremented), the semaphore + * could is non-negative, and there is no thread waiting for the count. + * In this case, the priority of the holder should not be boosted. + */ + +#if CONFIG_SEM_NNESTPRIO > 0 + DEBUGASSERT(htcb->npend_reprio == 0); +#endif + DEBUGASSERT(htcb->sched_priority == htcb->base_priority); +#endif + return 0; +} +#endif + +/**************************************************************************** + * Name: sem_dumpholder + ****************************************************************************/ + +#if defined(CONFIG_DEBUG) && defined(CONFIG_SEM_PHDEBUG) +static int sem_dumpholder(FAR struct semholder_s *pholder, FAR sem_t *sem, FAR void *arg) +{ +#if CONFIG_SEM_PREALLOCHOLDERS > 0 + dbg(" %08x: %08x %08x %04x\n", + pholder, pholder->flink, pholder->htcb, pholder->counts); +#else + dbg(" %08x: %08x %04x\n", pholder, pholder->htcb, pholder->counts); +#endif + return 0; +} +#endif + +/**************************************************************************** + * Name: sem_restoreholderprio + ****************************************************************************/ + +static int sem_restoreholderprio(FAR struct semholder_s *pholder, FAR sem_t *sem, FAR void *arg) +{ + FAR _TCB *htcb = (FAR _TCB *)pholder->htcb; +#if CONFIG_SEM_NNESTPRIO > 0 + FAR _TCB *stcb = (FAR _TCB *)arg; + int rpriority; + int i; + int j; +#endif + + /* Make sure that the hdoler thread is still active. If it exited without + * releasing its counts, then that would be a bad thing. But we can take no + * real action because we don't know know that the program is doing. Perhaps + * its plan is to kill a thread, then destroy the semaphore. + */ + + if (!sched_verifytcb(htcb)) + { + sdbg("TCB 0x%08x is a stale handle, counts lost\n", htcb); + sem_freeholder(sem, pholder); + } + + /* Was the priority of the holder thread boosted? If so, then drop its + * priority back to the correct level. What is the correct level? + */ + + else if (htcb->sched_priority != htcb->base_priority) + { +#if CONFIG_SEM_NNESTPRIO > 0 + /* Are there other, pending priority levels to revert to? */ + + if (htcb->npend_reprio < 1) + { + /* No... the holder thread has only been boosted once. Reset all + * priorities back to the base priority. + */ + + DEBUGASSERT(htcb->sched_priority == stcb->sched_priority && htcb->npend_reprio == 0); + sched_reprioritize(htcb, htcb->base_priority); + } + + /* There are multiple pending priority levels. The holder thread's "boosted" + * priority could greater than or equal to "stcb->sched_priority" (it could be + * greater if its priority we boosted becuase it also holds another semaphore). + */ + + else if (htcb->sched_priority <= stcb->sched_priority) + { + /* The holder thread has been boosted to the same priority as the waiter + * thread that just received the count. We will simply reprioritize + * to the next highest priority that we have in rpriority. + */ + + /* Find the highest pending priority and remove it from the list */ + + for (i = 1, j = 0; i < htcb->npend_reprio; i++) + { + if (htcb->pend_reprios[i] > htcb->pend_reprios[j]) + { + j = i; + } + } + + /* Remove the highest priority pending priority from the list */ + + rpriority = htcb->pend_reprios[j]; + i = htcb->npend_reprio - 1; + if (i > 0) + { + htcb->pend_reprios[j] = htcb->pend_reprios[i]; + } + + htcb->npend_reprio = i; + + /* And apply that priority to the thread (while retaining the base_priority) */ + + sched_setpriority(htcb, rpriority); + } + else + { + /* The holder thread has been boosted to a higher priority than the + * waiter task. The pending priority should be in the list (unless it + * was lost because of of list overflow or because the holder was + * reporioritize again unbeknownst to the priority inheritance logic). + * + * Search the list for the matching priority. + */ + + for (i = 0; i < htcb->npend_reprio; i++) + { + /* Does this pending priority match the priority of the thread + * that just received the count? + */ + + if (htcb->pend_reprios[i] == stcb->sched_priority) + { + /* Yes, remove it from the list */ + + j = htcb->npend_reprio - 1; + if (j > 0) + { + htcb->pend_reprios[i] = htcb->pend_reprios[j]; + } + + htcb->npend_reprio = j; + break; + } + } + } +#else + /* There is no alternative restore priorities, drop the priority + * of the holder thread all the way back to the threads "base" + * priority. + */ + + sched_reprioritize(htcb, htcb->base_priority); +#endif + } + + return 0; +} + +/**************************************************************************** + * Name: sem_restoreholderprioA + * + * Description: + * Reprioritize all holders except the currently executing task + * + ****************************************************************************/ + +static int sem_restoreholderprioA(FAR struct semholder_s *pholder, + FAR sem_t *sem, FAR void *arg) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + if (pholder->htcb != rtcb) + { + return sem_restoreholderprio(pholder, sem, arg); + } + + return 0; +} + +/**************************************************************************** + * Name: sem_restoreholderprioB + * + * Description: + * Reprioritize only the currently executing task + * + ****************************************************************************/ + +static int sem_restoreholderprioB(FAR struct semholder_s *pholder, + FAR sem_t *sem, FAR void *arg) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + if (pholder->htcb == rtcb) + { + (void)sem_restoreholderprio(pholder, sem, arg); + return 1; + } + + return 0; +} + +/**************************************************************************** + * Name: sem_restorebaseprio_irq + * + * Description: + * This function is called after the an interrupt handler posts a count on + * the semaphore. It will check if we need to drop the priority of any + * threads holding a count on the semaphore. Their priority could have + * been boosted while they held the count. + * + * Parameters: + * stcb - The TCB of the task that was just started (if any). If the + * post action caused a count to be given to another thread, then stcb + * is the TCB that received the count. Note, just because stcb received + * the count, it does not mean that it it is higher priority than other + * threads. + * sem - A reference to the semaphore being posted. + * - If the semaphore count is <0 then there are still threads waiting + * for a count. stcb should be non-null and will be higher priority + * than all of the other threads still waiting. + * - If it is ==0 then stcb refers to the thread that got the last count; + * no other threads are waiting. + * - If it is >0 then there should be no threads waiting for counts and + * stcb should be null. + * + * Return Value: + * None + * + * Assumptions: + * The scheduler is locked. + * + ****************************************************************************/ + +static inline void sem_restorebaseprio_irq(FAR _TCB *stcb, FAR sem_t *sem) +{ + /* Perfom the following actions only if a new thread was given a count. + * The thread that received the count should be the highest priority + * of all threads waiting for a count from the semphore. So in that + * case, the priority of all holder threads should be dropped to the + * next highest pending priority. + */ + + if (stcb) + { + /* Drop the priority of all holder threads */ + + (void)sem_foreachholder(sem, sem_restoreholderprio, stcb); + } + + /* If there are no tasks waiting for available counts, then all holders + * should be at their base priority. + */ + +#ifdef CONFIG_DEBUG + else + { + (void)sem_foreachholder(sem, sem_verifyholder, NULL); + } +#endif +} + +/**************************************************************************** + * Name: sem_restorebaseprio_task + * + * Description: + * This function is called after the current running task releases a + * count on the semaphore. It will check if we need to drop the priority + * of any threads holding a count on the semaphore. Their priority could + * have been boosted while they held the count. + * + * Parameters: + * stcb - The TCB of the task that was just started (if any). If the + * post action caused a count to be given to another thread, then stcb + * is the TCB that received the count. Note, just because stcb received + * the count, it does not mean that it it is higher priority than other + * threads. + * sem - A reference to the semaphore being posted. + * - If the semaphore count is <0 then there are still threads waiting + * for a count. stcb should be non-null and will be higher priority + * than all of the other threads still waiting. + * - If it is ==0 then stcb refers to the thread that got the last count; + * no other threads are waiting. + * - If it is >0 then there should be no threads waiting for counts and + * stcb should be null. + * + * Return Value: + * None + * + * Assumptions: + * The scheduler is locked. + * + ****************************************************************************/ + +static inline void sem_restorebaseprio_task(FAR _TCB *stcb, FAR sem_t *sem) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + FAR struct semholder_s *pholder; + + /* Perfom the following actions only if a new thread was given a count. + * The thread that received the count should be the highest priority + * of all threads waiting for a count from the semphore. So in that + * case, the priority of all holder threads should be dropped to the + * next highest pending priority. + */ + + if (stcb) + { + /* The currently executed thread should be the lower priority + * thread that just posted the count and caused this action. + * However, we cannot drop the priority of the currently running + * thread -- becuase that will cause it to be suspended. + * + * So, do this in two passes. First, reprioritizing all holders + * except for the running thread. + */ + + (void)sem_foreachholder(sem, sem_restoreholderprioA, stcb); + + /* Now, find an reprioritize only the ready to run task */ + + (void)sem_foreachholder(sem, sem_restoreholderprioB, stcb); + } + + /* If there are no tasks waiting for available counts, then all holders + * should be at their base priority. + */ + +#ifdef CONFIG_DEBUG + else + { + (void)sem_foreachholder(sem, sem_verifyholder, NULL); + } +#endif + + /* In any case, the currently executing task should have an entry in the + * list. Its counts were previously decremented; if it now holds no + * counts, then we need to remove it from the list of holders. + */ + + pholder = sem_findholder(sem, rtcb); + if (pholder) + { + /* When no more counts are held, remove the holder from the list. The + * count was decremented in sem_releaseholder. + */ + + if (pholder->counts <= 0) + { + sem_freeholder(sem, pholder); + } + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sem_initholders + * + * Description: + * Called from sem_initialize() to set up semaphore holder information. + * + * Parameters: + * None + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +void sem_initholders(void) +{ +#if CONFIG_SEM_PREALLOCHOLDERS > 0 + int i; + + /* Put all of the pre-allocated holder structures into free list */ + + g_freeholders = g_holderalloc; + for (i = 0; i < (CONFIG_SEM_PREALLOCHOLDERS-1); i++) + { + g_holderalloc[i].flink = &g_holderalloc[i+1]; + } + + g_holderalloc[CONFIG_SEM_PREALLOCHOLDERS-1].flink = NULL; +#endif +} + +/**************************************************************************** + * Name: sem_destroyholder + * + * Description: + * Called from sem_destroy() to handle any holders of a semaphore when + * it is destroyed. + * + * Parameters: + * sem - A reference to the semaphore being destroyed + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +void sem_destroyholder(FAR sem_t *sem) +{ + /* It is an error if a semaphore is destroyed while there are any holders + * (except perhaps the thread release the semaphore itself). Hmmm.. but + * we actually have to assume that the caller knows what it is doing because + * could have killed another thread that is the actual holder of the semaphore. + * We cannot make any assumptions about the state of the semaphore or the + * state of any of the holder threads. + * + * So just recover any stranded holders and hope the task knows what it is + * doing. + */ + +#if CONFIG_SEM_PREALLOCHOLDERS > 0 + if (sem->hhead) + { + sdbg("Semaphore destroyed with holders\n"); + (void)sem_foreachholder(sem, sem_recoverholders, NULL); + } +#else + if (sem->holder.htcb) + { + sdbg("Semaphore destroyed with holder\n"); + } + + sem->holder.htcb = NULL; +#endif +} + +/**************************************************************************** + * Name: sem_addholder + * + * Description: + * Called from sem_wait() when the calling thread obtains the semaphore + * + * Parameters: + * sem - A reference to the incremented semaphore + * + * Return Value: + * 0 (OK) or -1 (ERROR) if unsuccessful + * + * Assumptions: + * + ****************************************************************************/ + +void sem_addholder(FAR sem_t *sem) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + FAR struct semholder_s *pholder; + + /* Find or allocate a container for this new holder */ + + pholder = sem_findorallocateholder(sem, rtcb); + if (pholder) + { + /* Then set the holder and increment the number of counts held by this holder */ + + pholder->htcb = rtcb; + pholder->counts++; + } +} + +/**************************************************************************** + * Name: void sem_boostpriority(sem_t *sem) + * + * Description: + * + * + * Parameters: + * None + * + * Return Value: + * 0 (OK) or -1 (ERROR) if unsuccessful + * + * Assumptions: + * + ****************************************************************************/ + +void sem_boostpriority(FAR sem_t *sem) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + + /* Boost the priority of every thread holding counts on this semaphore + * that are lower in priority than the new thread that is waiting for a + * count. + */ + + (void)sem_foreachholder(sem, sem_boostholderprio, rtcb); +} + +/**************************************************************************** + * Name: sem_releaseholder + * + * Description: + * Called from sem_post() after a thread releases one count on the + * semaphore. + * + * Parameters: + * sem - A reference to the semaphore being posted + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +void sem_releaseholder(FAR sem_t *sem) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + FAR struct semholder_s *pholder; + + /* Find the container for this holder */ + + pholder = sem_findholder(sem, rtcb); + if (pholder && pholder->counts > 0) + { + /* Decrement the counts on this holder -- the holder will be freed + * later in sem_restorebaseprio. + */ + + pholder->counts--; + } +} + +/**************************************************************************** + * Name: sem_restorebaseprio + * + * Description: + * This function is called after the current running task releases a + * count on the semaphore or an interrupt handler posts a new count. It + * will check if we need to drop the priority of any threads holding a + * count on the semaphore. Their priority could have been boosted while + * they held the count. + * + * Parameters: + * stcb - The TCB of the task that was just started (if any). If the + * post action caused a count to be given to another thread, then stcb + * is the TCB that received the count. Note, just because stcb received + * the count, it does not mean that it it is higher priority than other + * threads. + * sem - A reference to the semaphore being posted. + * - If the semaphore count is <0 then there are still threads waiting + * for a count. stcb should be non-null and will be higher priority + * than all of the other threads still waiting. + * - If it is ==0 then stcb refers to the thread that got the last count; + * no other threads are waiting. + * - If it is >0 then there should be no threads waiting for counts and + * stcb should be null. + * + * Return Value: + * None + * + * Assumptions: + * The scheduler is locked. + * + ****************************************************************************/ + +void sem_restorebaseprio(FAR _TCB *stcb, FAR sem_t *sem) +{ + /* Check our assumptions */ + + DEBUGASSERT((sem->semcount > 0 && stcb == NULL) || + (sem->semcount <= 0 && stcb != NULL)); + + /* Handler semaphore counts posed from an interrupt handler differently + * from interrupts posted from threads. The primary difference is that + * if the semaphore is posted from a thread, then the poster thread is + * a player in the priority inheritance scheme. The interrupt handler + * externally injects the new count without otherwise participating + * itself. + */ + + if (up_interrupt_context()) + { + sem_restorebaseprio_irq(stcb, sem); + } + else + { + sem_restorebaseprio_task(stcb, sem); + } +} + +/**************************************************************************** + * Name: sem_canceled + * + * Description: + * Called from sem_waitirq() after a thread that was waiting for a semaphore + * count was awakened because of a signal and the semaphore wait has been + * canceled. This function restores the correct thread priority of each + * holder of the semaphore. + * + * Parameters: + * sem - A reference to the semaphore no longer being waited for + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_SIGNALS +void sem_canceled(FAR _TCB *stcb, FAR sem_t *sem) +{ + /* Check our assumptions */ + + DEBUGASSERT(sem->semcount <= 0); + + /* Adjust the priority of every holder as necessary */ + + (void)sem_foreachholder(sem, sem_restoreholderprio, stcb); +} +#endif + +/**************************************************************************** + * Name: sem_enumholders + * + * Description: + * Show information about threads currently waiting on this semaphore + * + * Parameters: + * sem - A reference to the semaphore + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#if defined(CONFIG_DEBUG) && defined(CONFIG_SEM_PHDEBUG) +void sem_enumholders(FAR sem_t *sem) +{ + (void)sem_foreachholder(sem, sem_dumpholder, NULL); +} +#endif + +/**************************************************************************** + * Name: sem_nfreeholders + * + * Description: + * Return the number of available holder containers. This is a good way + * to find out which threads are not calling sem_destroy. + * + * Parameters: + * sem - A reference to the semaphore + * + * Return Value: + * The number of available holder containers + * + * Assumptions: + * + ****************************************************************************/ + +#if defined(CONFIG_DEBUG) && defined(CONFIG_SEM_PHDEBUG) +int sem_nfreeholders(void) +{ +#if CONFIG_SEM_PREALLOCHOLDERS > 0 + FAR struct semholder_s *pholder; + int n; + + for (pholder = g_freeholders, n = 0; pholder; pholder = pholder->flink) n++; + return n; +#else + return 0; +#endif +} +#endif + +#endif /* CONFIG_PRIORITY_INHERITANCE */ diff --git a/nuttx/sched/sem_initialize.c b/nuttx/sched/sem_initialize.c new file mode 100644 index 000000000..d8b402825 --- /dev/null +++ b/nuttx/sched/sem_initialize.c @@ -0,0 +1,100 @@ +/**************************************************************************** + * schec/sem_initialize.c + * + * Copyright (C) 2007, 2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include + +#include "sem_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/* This is a list of dyanamically allocated named semaphores */ + +dq_queue_t g_nsems; + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sem_initialize + * + * Description: + * The control structures for all semaphores may be initialized by calling + * sem_initialize(). This should be done once at poweron. + * + * Parameters: + * None + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +void sem_initialize(void) +{ + /* Initialize the queue of named semaphores */ + + dq_init(&g_nsems); + + /* Initialize holder structures needed to support priority inheritiance */ + + sem_initholders(); +} diff --git a/nuttx/sched/sem_internal.h b/nuttx/sched/sem_internal.h new file mode 100644 index 000000000..434c551a4 --- /dev/null +++ b/nuttx/sched/sem_internal.h @@ -0,0 +1,131 @@ +/**************************************************************************** + * sched/sem_internal.h + * + * Copyright (C) 2007, 2009-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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. + * + ****************************************************************************/ + +#ifndef __SCHED_SEM_INTERNAL_H +#define __SCHED_SEM_INTERNAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Type Declarations + ****************************************************************************/ + +/* This is the named semaphore structure */ + +struct nsem_s +{ + FAR struct nsem_s *flink; /* Forward link */ + FAR struct nsem_s *blink; /* Backward link */ + uint16_t nconnect; /* Number of connections to semaphore */ + FAR char *name; /* Semaphore name (NULL if un-named) */ + bool unlinked; /* true if the semaphore has been unlinked */ + sem_t sem; /* The semaphore itself */ +}; + +typedef struct nsem_s nsem_t; + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/* This is a list of dyanamically allocated named semaphores */ + +extern dq_queue_t g_nsems; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/* Common semaphore logic */ + +EXTERN void weak_function sem_initialize(void); +EXTERN void sem_waitirq(FAR _TCB *wtcb, int errcode); +EXTERN FAR nsem_t *sem_findnamed(const char *name); + +/* Special logic needed only by priority inheritance to manage collections of + * holders of semaphores. + */ + +#ifdef CONFIG_PRIORITY_INHERITANCE +EXTERN void sem_initholders(void); +EXTERN void sem_destroyholder(FAR sem_t *sem); +EXTERN void sem_addholder(FAR sem_t *sem); +EXTERN void sem_boostpriority(FAR sem_t *sem); +EXTERN void sem_releaseholder(FAR sem_t *sem); +EXTERN void sem_restorebaseprio(FAR _TCB *stcb, FAR sem_t *sem); +# ifndef CONFIG_DISABLE_SIGNALS +EXTERN void sem_canceled(FAR _TCB *stcb, FAR sem_t *sem); +# else +# define sem_canceled(stcb, sem) +# endif +#else +# define sem_initholders() +# define sem_destroyholder(sem) +# define sem_addholder(sem) +# define sem_boostpriority(sem) +# define sem_releaseholder(sem) +# define sem_restorebaseprio(stcb,sem) +# define sem_canceled(stcb, sem) +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __SCHED_SEM_INTERNAL_H */ + diff --git a/nuttx/sched/sem_open.c b/nuttx/sched/sem_open.c new file mode 100644 index 000000000..817c36b49 --- /dev/null +++ b/nuttx/sched/sem_open.c @@ -0,0 +1,209 @@ +/**************************************************************************** + * sched/sem_open.c + * + * Copyright (C) 2007, 2008, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "sem_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sem_open + * + * Description: + * This function establishes a connection between named semaphores and a + * task. Following a call to sem_open() with the semaphore name, the task + * may reference the semaphore associated with name using the address + * returned by this call. The semaphore may be used in subsequent calls + * to sem_wait(), sem_trywait(), and sem_post(). The semaphore remains + * usable until the semaphore is closed by a successful call to sem_close(). + * + * If a task makes multiple calls to sem_open() with the same name, then + * the same semaphore address is returned (provided there have been no + * calls to sem_unlink()). + * + * Parameters: + * name - Semaphore name + * oflag - Semaphore creation options. This may either or both of the + * following bit settings. + * oflag = 0: Connect to the semaphore only if it already exists. + * oflag = O_CREAT: Connect to the semaphore if it exists, otherwise + * create the semaphore. + * oflag = O_CREAT|O_EXCL: Create a new semaphore + * unless one of this name already exists. + * Optional parameters. When the O_CREAT flag is specified, two optional + * parameters are expected: + * 1. mode_t mode (ignored), and + * 2. unsigned int value. This initial value of the semaphore. Valid + * initial values of the semaphore must be less than or equal to + * SEM_VALUE_MAX. + * + * Return Value: + * A pointer to sem_t or -1 (ERROR) if unsuccessful. + * + * Assumptions: + * + ****************************************************************************/ + +FAR sem_t *sem_open (FAR const char *name, int oflag, ...) +{ + int namelen; + FAR nsem_t *psem; + FAR sem_t *sem = (FAR sem_t*)ERROR; + va_list arg; /* Points to each un-named argument */ + mode_t mode; /* Creation mode parameter (ignored) */ + unsigned int value; /* Semaphore value parameter */ + + /* Make sure that a non-NULL name is supplied */ + + if (name) + { + /* The POSIX specification requires that the "check for the + * existence of a semaphore and the creation of the semaphore + * if it does not exist shall be atomic with respect to other + * processes executing sem_open()..." A simple sched_lock() + * should be sufficient to meet this requirement. + */ + + sched_lock(); + namelen = strlen(name); + if (namelen > 0) + { + /* See if the semaphore already exists */ + + psem = sem_findnamed(name); + if (psem) + { + /* It does. Check if the caller wanted to created + * a new semahore with this name. + */ + + if (!(oflag & O_CREAT) || !(oflag & O_EXCL)) + { + /* Allow a new connection to the semaphore */ + + psem->nconnect++; + sem = &psem->sem; + } + } + + /* It doesn't exist. Should we create one? */ + + else if ((oflag & O_CREAT) != 0) + { + /* Set up to get the optional arguments needed to create + * a message queue. + */ + + va_start(arg, oflag); + mode = va_arg(arg, mode_t); + value = va_arg(arg, unsigned int); + + /* Verify that a legal initial value was selected. */ + + if (value <= SEM_VALUE_MAX) + { + /* Allocate memory for the new semaphore */ + + psem = (FAR nsem_t*)kmalloc((sizeof(nsem_t) + namelen + 1)); + if (psem) + { + /* Initialize the named semaphore */ + + sem = &psem->sem; + sem_init(sem, 0, value); + + psem->nconnect = 1; + psem->unlinked = false; + psem->name = (FAR char*)psem + sizeof(nsem_t); + strcpy(psem->name, name); + + /* Add the new semaphore to the list of named + * semaphores + */ + + dq_addfirst((FAR dq_entry_t*)psem, &g_nsems); + } + + /* Clean-up variable argument stuff */ + + va_end(arg); + } + } + } + + sched_unlock(); + } + + return sem; +} + diff --git a/nuttx/sched/sem_post.c b/nuttx/sched/sem_post.c new file mode 100644 index 000000000..1c694b68c --- /dev/null +++ b/nuttx/sched/sem_post.c @@ -0,0 +1,182 @@ +/**************************************************************************** + * sched/sem_post.c + * + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include + +#include "os_internal.h" +#include "sem_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sem_post + * + * Description: + * When a task has finished with a semaphore, it will call sem_post(). + * This function unlocks the semaphore referenced by sem by performing the + * semaphore unlock operation on that semaphore. + * + * If the semaphore value resulting from this operation is positive, then + * no tasks were blocked waiting for the semaphore to become unlocked; the + * semaphore is simply incremented. + * + * If the value of the semaphore resulting from this operation is zero, + * then one of the tasks blocked waiting for the semaphore shall be + * allowed to return successfully from its call to sem_wait(). + * + * Parameters: + * sem - Semaphore descriptor + * + * Return Value: + * 0 (OK) or -1 (ERROR) if unsuccessful + * + * Assumptions: + * This function cannot be called from an interrupt handler. + * It assumes the currently executing task is the one that + * is performing the unlock. + * + ****************************************************************************/ + +int sem_post(FAR sem_t *sem) +{ + FAR _TCB *stcb = NULL; + int ret = ERROR; + irqstate_t saved_state; + + /* Make sure we were supplied with a valid semaphore. */ + + if (sem) + { + /* The following operations must be performed with interrupts + * disabled because sem_post() may be called from an interrupt + * handler. + */ + + saved_state = irqsave(); + + /* Perform the semaphore unlock operation. */ + + ASSERT(sem->semcount < SEM_VALUE_MAX); + sem_releaseholder(sem); + sem->semcount++; + +#ifdef CONFIG_PRIORITY_INHERITANCE + /* Don't let any unblocked tasks run until we complete any priority + * restoration steps. Interrupts are disabled, but we do not want + * the head of the read-to-run list to be modified yet. + * + * NOTE: If this sched_lock is called from an interrupt handler, it + * will do nothing. + */ + + sched_lock(); +#endif + /* If the result of of semaphore unlock is non-positive, then + * there must be some task waiting for the semaphore. + */ + + if (sem->semcount <= 0) + { + /* Check if there are any tasks in the waiting for semaphore + * task list that are waiting for this semaphore. This is a + * prioritized list so the first one we encounter is the one + * that we want. + */ + + for (stcb = (FAR _TCB*)g_waitingforsemaphore.head; + (stcb && stcb->waitsem != sem); + stcb = stcb->flink); + + if (stcb) + { + /* It is, let the task take the semaphore */ + + stcb->waitsem = NULL; + + /* Restart the waiting task. */ + + up_unblock_task(stcb); + } + } + + /* Check if we need to drop the priority of any threads holding + * this semaphore. The priority could have been boosted while they + * held the semaphore. + */ + +#ifdef CONFIG_PRIORITY_INHERITANCE + sem_restorebaseprio(stcb, sem); + sched_unlock(); +#endif + ret = OK; + + /* Interrupts may now be enabled. */ + + irqrestore(saved_state); + } + + return ret; +} diff --git a/nuttx/sched/sem_timedwait.c b/nuttx/sched/sem_timedwait.c new file mode 100644 index 000000000..6a4724406 --- /dev/null +++ b/nuttx/sched/sem_timedwait.c @@ -0,0 +1,286 @@ +/**************************************************************************** + * sched/sem_timedwait.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "os_internal.h" +#include "clock_internal.h" +#include "sem_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sem_timeout + * + * Description: + * This function is called if the timeout elapses before the message queue + * becomes non-empty. + * + * Parameters: + * argc - the number of arguments (should be 1) + * pid - the task ID of the task to wakeup + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void sem_timeout(int argc, uint32_t pid) +{ + FAR _TCB *wtcb; + irqstate_t flags; + + /* Disable interrupts to avoid race conditions */ + + flags = irqsave(); + + /* Get the TCB associated with this pid. It is possible that + * task may no longer be active when this watchdog goes off. + */ + + wtcb = sched_gettcb((pid_t)pid); + + /* It is also possible that an interrupt/context switch beat us to the + * punch and already changed the task's state. + */ + + if (wtcb && wtcb->task_state == TSTATE_WAIT_SEM) + { + /* Cancel the semaphore wait */ + + sem_waitirq(wtcb, ETIMEDOUT); + } + + /* Interrupts may now be enabled. */ + + irqrestore(flags); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sem_timedwait + * + * Description: + * This function will lock the semaphore referenced by sem as in the + * sem_wait() function. However, if the semaphore cannot be locked without + * waiting for another process or thread to unlock the semaphore by + * performing a sem_post() function, this wait will be terminated when the + * specified timeout expires. + * + * The timeout will expire when the absolute time specified by abstime + * passes, as measured by the clock on which timeouts are based (that is, + * when the value of that clock equals or exceeds abstime), or if the + * absolute time specified by abstime has already been passed at the + * time of the call. + * + * Parameters: + * sem - Semaphore object + * abstime - The absolute time to wait until a timeout is declared. + * + * Return Value: + * One success, the length of the selected message in bytes.is + * returned. On failure, -1 (ERROR) is returned and the errno + * is set appropriately: + * + * EINVAL The sem argument does not refer to a valid semaphore. Or the + * thread would have blocked, and the abstime parameter specified + * a nanoseconds field value less than zero or greater than or + * equal to 1000 million. + * ETIMEDOUT The semaphore could not be locked before the specified timeout + * expired. + * EDEADLK A deadlock condition was detected. + * EINTR A signal interrupted this function. + * + ****************************************************************************/ + +int sem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime) +{ + WDOG_ID wdog; + irqstate_t flags; + int ticks; + int err; + int ret = ERROR; + + DEBUGASSERT(up_interrupt_context() == false); + + /* Verify the input parameters and, in case of an error, set + * errno appropriately. + */ + +#ifdef CONFIG_DEBUG + if (!abstime || !sem) + { + err = EINVAL; + goto errout; + } +#endif + + /* Create a watchdog. We will not actually need this watchdog + * unless the the semaphore is unavailable, but we will reserve it up + * front before we enter the following critical section. + */ + + wdog = wd_create(); + if (!wdog) + { + err = 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 asynchronoulsy + * 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 == 0) + { + /* We got it! */ + + irqrestore(flags); + wd_delete(wdog); + return OK; + } + + /* We will have to wait for the semphore. Make sure that we were provided + * with a valid timeout. + */ + + if (abstime->tv_sec < 0 || abstime->tv_nsec > 1000000000) + { + err = EINVAL; + goto errout_disabled; + } + + /* Convert the timespec to clock ticks. We must have interrupts + * disabled here so that this time stays valid until the wait begins. + */ + + err = clock_abstime2ticks(CLOCK_REALTIME, abstime, &ticks); + + /* If the time has already expired return immediately. */ + + if (err == OK && ticks <= 0) + { + err = ETIMEDOUT; + goto errout_disabled; + } + + /* Handle any time-related errors */ + + if (err != OK) + { + goto errout_disabled; + } + + /* Start the watchdog */ + + err = OK; + wd_start(wdog, ticks, (wdentry_t)sem_timeout, 1, getpid()); + + /* Now perform the blocking wait */ + + ret = sem_wait(sem); + + /* Stop the watchdog timer */ + + wd_cancel(wdog); + + /* We can now restore interrupts and delete the watchdog */ + + irqrestore(flags); + wd_delete(wdog); + + /* We are either returning success or an error detected by sem_wait() + * or the timeout detected by sem_timeout(). The 'errno' value has + * been set appropriately by sem_wait() or sem_timeout() in those + * cases. + */ + + return ret; + +/* Error exits */ + +errout_disabled: + irqrestore(flags); + wd_delete(wdog); +errout: + set_errno(err); + return ERROR; +} diff --git a/nuttx/sched/sem_trywait.c b/nuttx/sched/sem_trywait.c new file mode 100644 index 000000000..cbd8dae69 --- /dev/null +++ b/nuttx/sched/sem_trywait.c @@ -0,0 +1,142 @@ +/**************************************************************************** + * sched/sem_trywait.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include + +#include "os_internal.h" +#include "sem_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sem_trywait + * + * Description: + * This function locks the specified semaphore only if the semaphore is + * currently not locked. Otherwise, it locks the semaphore. In either + * case, the call returns without blocking. + * + * Parameters: + * sem - the semaphore descriptor + * + * Return Value: + * 0 (OK) or -1 (ERROR) if unsuccessful. If this function returns -1 + * (ERROR),then the cause of the failure will be reported in "errno" as: + * + * EINVAL: Invalid attempt to get the semaphore + * EAGAIN: The semaphore is not available. + * + * Assumptions: + * + ****************************************************************************/ + +int sem_trywait(FAR sem_t *sem) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + irqstate_t saved_state; + int ret = ERROR; + + /* This API should not be called from interrupt handlers */ + + DEBUGASSERT(up_interrupt_context() == false) + + /* Assume any errors reported are due to invalid arguments. */ + + set_errno(EINVAL); + + if (sem) + { + /* The following operations must be performed with interrupts disabled + * because sem_post() may be called from an interrupt handler. + */ + + saved_state = irqsave(); + + /* Any further errors could only be occurred because the semaphore + * is not available. + */ + + set_errno(EAGAIN); + + /* If the semaphore is available, give it to the requesting task */ + + if (sem->semcount > 0) + { + /* It is, let the task take the semaphore */ + + sem->semcount--; + rtcb->waitsem = NULL; + ret = OK; + } + + /* Interrupts may now be enabled. */ + + irqrestore(saved_state); + } + + return ret; +} diff --git a/nuttx/sched/sem_unlink.c b/nuttx/sched/sem_unlink.c new file mode 100644 index 000000000..6fe011540 --- /dev/null +++ b/nuttx/sched/sem_unlink.c @@ -0,0 +1,140 @@ +/**************************************************************************** + * sched/sem_unlink.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include + +#include "os_internal.h" +#include "sem_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sem_unlink + * + * Description: + * This function removes the semaphore named by the input parameter 'name.' + * If the semaphore named by 'name' is currently referenced by other task, + * the sem_unlink() will have no effect on the state of the semaphore. If + * one or more processes have the semaphore open when sem_unlink() is + * called, destruction of the semaphore will be postponed until all + * references to the semaphore have been destroyed by calls of sem_close(). + * + * Parameters: + * name - Semaphore name + * + * Return Value: + * 0 (OK), or -1 (ERROR) if unsuccessful. + * + * Assumptions: + * + ****************************************************************************/ + +int sem_unlink(FAR const char *name) +{ + FAR nsem_t *psem; + int ret = ERROR; + + /* Verify the input values */ + + if (name) + { + sched_lock(); + + /* Find the named semaphore */ + + psem = sem_findnamed(name); + + /* Check if the semaphore was found */ + + if (psem) + { + /* If the named semaphore was found and if there are no + * connects to it, then deallocate it + */ + + if (!psem->nconnect) + { + dq_rem((FAR dq_entry_t*)psem, &g_nsems); + sched_free(psem); + } + + /* If one or more process still has the semaphore open, + * then just mark it as unlinked. The unlinked semaphore will + * be deleted when the final process closes the semaphore. + */ + + else + { + psem->unlinked = true; + } + ret = OK; + } + + sched_unlock(); + } + + return ret; +} diff --git a/nuttx/sched/sem_wait.c b/nuttx/sched/sem_wait.c new file mode 100644 index 000000000..9dfbaa6c3 --- /dev/null +++ b/nuttx/sched/sem_wait.c @@ -0,0 +1,216 @@ +/**************************************************************************** + * sched/sem_wait.c + * + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include + +#include "os_internal.h" +#include "sem_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sem_wait + * + * Description: + * This function attempts to lock the semaphore referenced by 'sem'. If + * the semaphore value is (<=) zero, then the calling task will not return + * until it successfully acquires the lock. + * + * Parameters: + * sem - Semaphore descriptor. + * + * Return Value: + * 0 (OK), or -1 (ERROR) is unsuccessful + * If this function returns -1 (ERROR), then the cause of the failure will + * be reported in 'errno' as: + * - EINVAL: Invalid attempt to get the semaphore + * - EINTR: The wait was interrupted by the receipt of a signal. + * + * Assumptions: + * + ****************************************************************************/ + +int sem_wait(FAR sem_t *sem) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + int ret = ERROR; + irqstate_t saved_state; + + /* This API should not be called from interrupt handlers */ + + DEBUGASSERT(up_interrupt_context() == false) + + /* Assume any errors reported are due to invalid arguments. */ + + errno = EINVAL; + + if (sem) + { + /* The following operations must be performed with interrupts + * disabled because sem_post() may be called from an interrupt + * handler. + */ + + saved_state = irqsave(); + + /* Check if the lock is available */ + + if (sem->semcount > 0) + { + /* It is, let the task take the semaphore. */ + + sem->semcount--; + sem_addholder(sem); + rtcb->waitsem = NULL; + ret = OK; + } + + /* The semaphore is NOT available, We will have to block the + * current thread of execution. + */ + + else + { + /* First, verify that the task is not already waiting on a + * semaphore + */ + + if (rtcb->waitsem != NULL) + { + PANIC(OSERR_BADWAITSEM); + } + + /* Handle the POSIX semaphore (but don't set the owner yet) */ + + sem->semcount--; + + /* Save the waited on semaphore in the TCB */ + + rtcb->waitsem = sem; + + /* If priority inheritance is enabled, then check the priority of + * the holder of the semaphore. + */ + +#ifdef CONFIG_PRIORITY_INHERITANCE + /* Disable context switching. The following operations must be + * atomic with regard to the scheduler. + */ + + sched_lock(); + + /* Boost the priority of any threads holding a count on the + * semaphore. + */ + + sem_boostpriority(sem); +#endif + /* Add the TCB to the prioritized semaphore wait queue */ + + errno = 0; + up_block_task(rtcb, TSTATE_WAIT_SEM); + + /* When we resume at this point, either (1) the semaphore has been + * assigned to this thread of execution, or (2) the semaphore wait + * has been interrupted by a signal or a timeout. We can detect these + * latter cases be examining the errno value. + * + * In the event that the semaphore wait was interrupted by a signal or + * a timeout, certain semaphore clean-up operations have already been + * performed (see sem_waitirq.c). Specifically: + * + * - sem_canceled() was called to restore the priority of all threads + * that hold a reference to the semaphore, + * - The semaphore count was decremented, and + * - tcb->waitsem was nullifed. + * + * It is necesaary to do these things in sem_waitirq.c because a long + * time may elapse between the time that the signal was issued and + * this thread is awakened and this leaves a door open to several + * race conditions. + */ + + if (errno != EINTR && errno != ETIMEDOUT) + { + /* Not awakened by a signal or a timeout... We hold the semaphore */ + + sem_addholder(sem); + ret = OK; + } + +#ifdef CONFIG_PRIORITY_INHERITANCE + sched_unlock(); +#endif + } + + /* Interrupts may now be enabled. */ + + irqrestore(saved_state); + } + + return ret; +} diff --git a/nuttx/sched/sem_waitirq.c b/nuttx/sched/sem_waitirq.c new file mode 100644 index 000000000..3d3af18de --- /dev/null +++ b/nuttx/sched/sem_waitirq.c @@ -0,0 +1,145 @@ +/**************************************************************************** + * sched/sem_waitirq.c + * + * Copyright (C) 2007-2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include + +#include "sem_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sem_waitirq + * + * Description: + * This function is called when a signal is received by a task that is + * waiting on a semaphore. According to the POSIX spec, "...the calling + * thread shall not return from the call to [sem_wait] until it either + * locks the semaphore or the call is interrupted by a signal." + * + * Parameters: + * wtcb - A pointer to the TCB of the task that is waiting on a + * semphaphore, but has received a signal or timeout instead. + * errcode - EINTR if the semaphore wait was awakened by a signal; + * ETIMEDOUT if awakened by a timeout + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +void sem_waitirq(FAR _TCB *wtcb, int errcode) +{ + irqstate_t saved_state; + + /* Disable interrupts. This is necessary (unfortunately) because an + * interrupt handler may attempt to post the semaphore while we are + * doing this. + */ + + saved_state = irqsave(); + + /* It is possible that an interrupt/context switch beat us to the punch + * and already changed the task's state. + */ + + if (wtcb->task_state == TSTATE_WAIT_SEM) + { + sem_t *sem = wtcb->waitsem; + DEBUGASSERT(sem != NULL && sem->semcount < 0); + + /* Restore the correct priority of all threads that hold references + * to this semaphore. + */ + + sem_canceled(wtcb, sem); + + /* And increment the count on the semaphore. This releases the count + * that was taken by sem_post(). This count decremented the semaphore + * count to negative and caused the thread to be blocked in the first + * place. + */ + + sem->semcount++; + + /* Indicate that the semaphore wait is over. */ + + wtcb->waitsem = NULL; + + /* Mark the errno value for the thread. */ + + wtcb->pterrno = errcode; + + /* Restart the task. */ + + up_unblock_task(wtcb); + } + + /* Interrupts may now be enabled. */ + + irqrestore(saved_state); +} + diff --git a/nuttx/sched/sig_action.c b/nuttx/sched/sig_action.c new file mode 100644 index 000000000..fef5f1558 --- /dev/null +++ b/nuttx/sched/sig_action.c @@ -0,0 +1,272 @@ +/**************************************************************************** + * sched/sig_action.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include + +#include "os_internal.h" +#include "sig_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define COPY_SIGACTION(t,f) \ + { (t)->sa_sigaction = (f)->sa_sigaction; \ + (t)->sa_mask = (f)->sa_mask; \ + (t)->sa_flags = (f)->sa_flags; } + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sig_allocateaction + * + * Description: + * Allocate a new element for a sigaction queue + * + ****************************************************************************/ + +static FAR sigactq_t *sig_allocateaction(void) +{ + FAR sigactq_t *sigact; + + /* Try to get the signal action structure from the free list */ + + sigact = (FAR sigactq_t*)sq_remfirst(&g_sigfreeaction); + + /* Check if we got one. */ + + if (!sigact) + { + /* Add another block of signal actions to the list */ + + sig_allocateactionblock(); + + /* And try again */ + + sigact = (FAR sigactq_t*)sq_remfirst(&g_sigfreeaction); + if (!sigact) + { + PANIC(OSERR_OUTOFMEMORY); + } + } + + return sigact; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sigaction + * + * Description: + * This function allows the calling process to examine and/or specify the + * action to be associated with a specific signal. + * + * The structure sigaction, used to describe an action to be taken, is + * defined to include the following members: + * + * - sa_u.sa_handler: Pointer to a signal-catching function + * - sa_u.sa_sigaction: Alternative form of the signal-catching function + * - sa_mask: An additional set of signals to be blocked during execution + * of a signal catching function + * - sa_flags. Special flags to affect the behavior of a signal. + * + * If the argument 'act' is not NULL, it points to a structure specifying + * the action to be associated with the specified signal. If the argument + * 'oact' is not NULL, the action previously associated with the signal + * is stored in the location pointed to by the argument 'oact.' + * + * When a signal is caught by a signal-catching function installed by + * sigaction() function, a new signal mask is calculated and installed for + * the duration of the signal-catching function. This mask is formed by + * taking the union of the current signal mask and the value of the + * sa_mask for the signal being delivered and then including the signal + * being delivered. If and when the user's signal handler returns, the + * original signal mask is restored. + * + * Once an action is installed for a specific signal, it remains installed + * until another action is explicitly requested by another call to sigaction(). + * + * Parameters: + * sig - Signal of interest + * act - Location of new handler + * oact - Location to store only handler + * + * Return Value: + * 0 (OK), or -1 (ERROR) if the signal number is invalid. + * (errno is not set) + * + * Assumptions: + * + * POSIX Compatibility: + * - Special values of sa_handler in the struct sigaction + * act input not handled (SIG_DFL, SIG_IGN). + * - All sa_flags in struct sigaction of act input are + * ignored (all treated like SA_SIGINFO). + * + ****************************************************************************/ + +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; +} + +/**************************************************************************** + * Name: sig_releaseaction + * + * Description: + * Deallocate a sigaction Q entry + * + ****************************************************************************/ + +void sig_releaseaction(FAR sigactq_t *sigact) +{ + /* Just put it back on the free list */ + + sq_addlast((FAR sq_entry_t*)sigact, &g_sigfreeaction); +} diff --git a/nuttx/sched/sig_allocatependingsigaction.c b/nuttx/sched/sig_allocatependingsigaction.c new file mode 100644 index 000000000..15d6470ca --- /dev/null +++ b/nuttx/sched/sig_allocatependingsigaction.c @@ -0,0 +1,137 @@ +/************************************************************************ + * sched/sig_allocatependingsigaction.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include + +#include "os_internal.h" +#include "sig_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sig_allocatependingsigaction + * + * Description: + * Allocate a new element for the pending signal action queue + * + ************************************************************************/ + +FAR sigq_t *sig_allocatependingsigaction(void) +{ + FAR sigq_t *sigq; + irqstate_t saved_state; + + /* Check if we were called from an interrupt handler. */ + + if (up_interrupt_context()) + { + /* Try to get the pending signal action structure from the free list */ + + sigq = (FAR sigq_t*)sq_remfirst(&g_sigpendingaction); + + /* If so, then try the special list of structures reserved for + * interrupt handlers + */ + + if (!sigq) + { + sigq = (FAR sigq_t*)sq_remfirst(&g_sigpendingirqaction); + } + } + + /* If we were not called from an interrupt handler, then we are + * free to allocate pending signal action structures if necessary. */ + + else + { + /* Try to get the pending signal action structure from the free list */ + + saved_state = irqsave(); + sigq = (FAR sigq_t*)sq_remfirst(&g_sigpendingaction); + irqrestore(saved_state); + + /* Check if we got one. */ + + if (!sigq) + { + /* No...Try the resource pool */ + + if (!sigq) + { + sigq = (FAR sigq_t *)kmalloc((sizeof (sigq_t))); + } + + /* Check if we got an allocated message */ + + if (sigq) + { + sigq->type = SIG_ALLOC_DYN; + } + } + } + + return sigq; +} + diff --git a/nuttx/sched/sig_cleanup.c b/nuttx/sched/sig_cleanup.c new file mode 100644 index 000000000..4dcc04f8b --- /dev/null +++ b/nuttx/sched/sig_cleanup.c @@ -0,0 +1,118 @@ +/************************************************************************ + * sched/sig_cleanup.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include + +#include "os_internal.h" +#include "sig_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sig_cleanup + * + * Description: + * Deallocate all signal-related lists in a TCB. This function is + * called only at task deletion time. The caller is expected to have + * assured the critical section necessary to perform this action. + * + ************************************************************************/ + +void sig_cleanup(FAR _TCB *stcb) +{ + FAR sigactq_t *sigact; + FAR sigq_t *sigq; + FAR sigpendq_t *sigpend; + + /* Deallocate all entries in the list of signal actions */ + + while ((sigact = (FAR sigactq_t*)sq_remfirst(&stcb->sigactionq)) != NULL) + { + sig_releaseaction(sigact); + } + + /* Deallocate all entries in the list of pending signals */ + + while ((sigpend = (FAR sigpendq_t*)sq_remfirst(&stcb->sigpendingq)) != NULL) + { + sig_releasependingsignal(sigpend); + } + + /* Deallocate all entries in the list of pending signal actions */ + + while ((sigq = (FAR sigq_t*)sq_remfirst(&stcb->sigpendactionq)) != NULL) + { + sig_releasependingsigaction(sigq); + } + + /* Deallocate all entries in the list of posted signal actions */ + + while ((sigq = (FAR sigq_t*)sq_remfirst(&stcb->sigpostedq)) != NULL) + { + sig_releasependingsigaction(sigq); + } + + /* Misc. signal-related clean-up */ + + stcb->sigprocmask = ALL_SIGNAL_SET; + stcb->sigwaitmask = NULL_SIGNAL_SET; +} diff --git a/nuttx/sched/sig_deliver.c b/nuttx/sched/sig_deliver.c new file mode 100644 index 000000000..a1297fbc2 --- /dev/null +++ b/nuttx/sched/sig_deliver.c @@ -0,0 +1,159 @@ +/**************************************************************************** + * sched/sig_deliver.c + * + * Copyright (C) 2007, 2008, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include +#include + +#include "os_internal.h" +#include "sem_internal.h" +#include "sig_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sig_deliver + * + * Description: + * This function is called on the thread of execution of the signal + * receiving task. It processes all queued signals then returns. + * + ****************************************************************************/ + +void sig_deliver(FAR _TCB *stcb) +{ + FAR sigq_t *sigq; + FAR sigq_t *next; + sigset_t savesigprocmask; + irqstate_t saved_state; + int saved_errno; + + sched_lock(); + + /* Save the thread errno. When we finished dispatching the + * signal actions and resume the task, the errno value must + * be unchanged by the operation of the signal handling. In + * particular, the EINTR indication that says that the task + * was reawakened by a signal must be retained. + */ + + saved_errno = stcb->pterrno; + for (sigq = (FAR sigq_t*)stcb->sigpendactionq.head; (sigq); sigq = next) + { + next = sigq->flink; + sdbg("Sending signal sigq=0x%x\n", sigq); + + /* Remove the signal structure from the sigpendactionq and place it + * in the sigpostedq. NOTE: Since signals are processed one at a + * time, there should never be more than one signal in the sigpostedq + */ + + saved_state = irqsave(); + sq_rem((FAR sq_entry_t*)sigq, &(stcb->sigpendactionq)); + sq_addlast((FAR sq_entry_t*)sigq, &(stcb->sigpostedq)); + irqrestore(saved_state); + + /* Call the signal handler (unless the signal was cancelled) + * + * Save a copy of the old sigprocmask and install the new + * (temporary) sigprocmask. The new sigprocmask is the union + * of the current sigprocmask and the sa_mask for the signal being + * delivered plus the signal being delivered. + */ + + savesigprocmask = stcb->sigprocmask; + stcb->sigprocmask = savesigprocmask | sigq->mask | SIGNO2SET(sigq->info.si_signo); + + /* Deliver the signal */ + + (*sigq->action.sighandler)(sigq->info.si_signo, &sigq->info, NULL); + + /* Restore the original sigprocmask */ + + stcb->sigprocmask = savesigprocmask; + + /* Now, handle the (rare?) case where (a) a blocked signal was + * received while the signal handling executed but (b) restoring the + * original sigprocmask will unblock the signal. + */ + + sig_unmaskpendingsignal(); + + /* Remove the signal from the sigpostedq */ + + saved_state = irqsave(); + sq_rem((FAR sq_entry_t*)sigq, &(stcb->sigpostedq)); + irqrestore(saved_state); + + /* Then deallocate it */ + + sig_releasependingsigaction(sigq); + } + + stcb->pterrno = saved_errno; + sched_unlock(); +} + diff --git a/nuttx/sched/sig_findaction.c b/nuttx/sched/sig_findaction.c new file mode 100644 index 000000000..4115332b6 --- /dev/null +++ b/nuttx/sched/sig_findaction.c @@ -0,0 +1,100 @@ +/************************************************************************ + * sched/sig_findaction.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include "sig_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sig_findaction + * + * Description: + * Allocate a new element for a signal queue + * + ************************************************************************/ + +FAR sigactq_t *sig_findaction(FAR _TCB *stcb, int signo) +{ + FAR sigactq_t *sigact = NULL; + + /* Verify the caller's sanity */ + + if (stcb) + { + /* Sigactions can only be assigned to the currently executing + * thread. So, a simple lock ought to give us sufficient + * protection. + */ + + sched_lock(); + + /* Seach the list for a sigaction on this signal */ + + for(sigact = (FAR sigactq_t*)stcb->sigactionq.head; + ((sigact) && (sigact->signo != signo)); + sigact = sigact->flink); + + sched_unlock(); + } + + return sigact; +} diff --git a/nuttx/sched/sig_initialize.c b/nuttx/sched/sig_initialize.c new file mode 100644 index 000000000..966d818a1 --- /dev/null +++ b/nuttx/sched/sig_initialize.c @@ -0,0 +1,271 @@ +/************************************************************************ + * sched/sig_initialize.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include + +#include "os_internal.h" +#include "sig_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/* The g_sigfreeaction data structure is a list of available signal + * action structures. + */ + +sq_queue_t g_sigfreeaction; + +/* The g_sigpendingaction data structure is a list of available pending + * signal action structures. + */ + +sq_queue_t g_sigpendingaction; + +/* The g_sigpendingirqaction is a list of available pending signal actions + * that are reserved for use by interrupt handlers. + */ + +sq_queue_t g_sigpendingirqaction; + +/* The g_sigpendingsignal data structure is a list of available pending + * signal structures. + */ + +sq_queue_t g_sigpendingsignal; + +/* The g_sigpendingirqsignal data structure is a list of available + * pending signal structures that are reserved for use by interrupt + * handlers. + */ + +sq_queue_t g_sigpendingirqsignal; + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/* g_sigactionalloc is a pointer to the start of the allocated blocks of + * signal actions. + */ + +static sigactq_t *g_sigactionalloc; + +/* g_sigpendingactionalloc is a pointer to the start of the allocated + * blocks of pending signal actions. + */ + +static sigq_t *g_sigpendingactionalloc; + +/* g_sigpendingirqactionalloc is a pointer to the start of the allocated + * block of pending signal actions. + */ + +static sigq_t *g_sigpendingirqactionalloc; + +/* g_sigpendingsignalalloc is a pointer to the start of the allocated + * blocks of pending signals. + */ + +static sigpendq_t *g_sigpendingsignalalloc; + +/* g_sigpendingirqsignalalloc is a pointer to the start of the allocated + * blocks of pending signals. + */ + +static sigpendq_t *g_sigpendingirqsignalalloc; + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +static sigq_t *sig_allocateblock(sq_queue_t *siglist, uint16_t nsigs, + uint8_t sigtype); +static sigpendq_t *sig_allocatependingsignalblock(sq_queue_t *siglist, + uint16_t nsigs, uint8_t sigtype); + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Name: sig_allocateblock + * + * Description: + * Allocate a block of pending signal actions and place them + * on the free list. + * + ************************************************************************/ + +static sigq_t *sig_allocateblock(sq_queue_t *siglist, uint16_t nsigs, + uint8_t sigtype) +{ + sigq_t *sigqalloc; + sigq_t *sigq; + int i; + + /* Allocate a block of pending signal actions */ + + sigqalloc = (sigq_t*)kmalloc((sizeof(sigq_t)) * nsigs); + + sigq = sigqalloc; + for (i = 0; i < nsigs; i++) + { + sigq->type = sigtype; + sq_addlast((FAR sq_entry_t*)sigq++, siglist); + } + + return sigqalloc; +} + +/************************************************************************ + * Name: sig_allocatependingsignalblock + * + * Description: + * Allocate a block of pending signal structures and place them on + * the free list. + * + ************************************************************************/ + +static sigpendq_t *sig_allocatependingsignalblock(sq_queue_t *siglist, + uint16_t nsigs, uint8_t sigtype) +{ + sigpendq_t *sigpendalloc; + sigpendq_t *sigpend; + int i; + + /* Allocate a block of pending signal structures */ + + sigpendalloc = + (sigpendq_t*)kmalloc((sizeof(sigpendq_t)) * nsigs); + + sigpend = sigpendalloc; + for (i = 0; i < nsigs; i++) + { + sigpend->type = sigtype; + sq_addlast((FAR sq_entry_t*)sigpend++, siglist); + } + + return sigpendalloc; +} + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sig_initialize + * + * Description: + * Perform one-time power-up initialization + * + ************************************************************************/ + +void sig_initialize(void) +{ + /* Initialize free lists */ + + sq_init(&g_sigfreeaction); + sq_init(&g_sigpendingaction); + sq_init(&g_sigpendingirqaction); + sq_init(&g_sigpendingsignal); + sq_init(&g_sigpendingirqsignal); + + /* Add a block of signal structures to each list */ + + g_sigpendingactionalloc = + sig_allocateblock(&g_sigpendingaction, + NUM_PENDING_ACTIONS, + SIG_ALLOC_FIXED); + + g_sigpendingirqactionalloc = + sig_allocateblock(&g_sigpendingirqaction, + NUM_PENDING_INT_ACTIONS, + SIG_ALLOC_IRQ); + + sig_allocateactionblock(); + + g_sigpendingsignalalloc = + sig_allocatependingsignalblock(&g_sigpendingsignal, + NUM_SIGNALS_PENDING, + SIG_ALLOC_FIXED); + + g_sigpendingirqsignalalloc = + sig_allocatependingsignalblock(&g_sigpendingirqsignal, + NUM_INT_SIGNALS_PENDING, + SIG_ALLOC_IRQ); +} + +/************************************************************************ + * Name: sig_allocateactionblock + * + * Description: + * Allocate a block of signal actions and place them + * on the free list. + * + ************************************************************************/ + +void sig_allocateactionblock(void) +{ + sigactq_t *sigact; + int i; + + /* Allocate a block of signal actions */ + + g_sigactionalloc = + (sigactq_t*)kmalloc((sizeof(sigactq_t)) * NUM_SIGNAL_ACTIONS); + + sigact = g_sigactionalloc; + for (i = 0; i < NUM_SIGNAL_ACTIONS; i++) + { + sq_addlast((FAR sq_entry_t*)sigact++, &g_sigfreeaction); + } +} diff --git a/nuttx/sched/sig_internal.h b/nuttx/sched/sig_internal.h new file mode 100644 index 000000000..6c0641742 --- /dev/null +++ b/nuttx/sched/sig_internal.h @@ -0,0 +1,190 @@ +/**************************************************************************** + * sched/sig_internal.h + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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. + * + ****************************************************************************/ + +#ifndef __SCHED_SIG_INTERNAL_H +#define __SCHED_SIG_INTERNAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* The following definition determines the number of signal structures to + * allocate in a block + */ + +#define NUM_SIGNAL_ACTIONS 16 +#define NUM_PENDING_ACTIONS 16 +#define NUM_PENDING_INT_ACTIONS 8 +#define NUM_SIGNALS_PENDING 16 +#define NUM_INT_SIGNALS_PENDING 8 + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + +enum sigalloc_e +{ + SIG_ALLOC_FIXED = 0, /* pre-allocated; never freed */ + SIG_ALLOC_DYN, /* dynamically allocated; free when unused */ + SIG_ALLOC_IRQ /* Preallocated, reserved for interrupt handling */ +}; +typedef enum sigalloc_e sigalloc_t; + +/* The following defines the sigaction queue entry */ + +struct sigactq +{ + FAR struct sigactq *flink; /* Forward link */ + struct sigaction act; /* Sigaction data */ + uint8_t signo; /* Signal associated with action */ +}; +typedef struct sigactq sigactq_t; + +/* The following defines the queue structure within each TCB to hold pending + * signals received by the task. These are signals that cannot be processed + * because: (1) the task is not waiting for them, or (2) the task has no + * action associated with the signal. + */ + +struct sigpendq +{ + FAR struct sigpendq *flink; /* Forward link */ + siginfo_t info; /* Signal information */ + uint8_t type; /* (Used to manage allocations) */ +}; +typedef struct sigpendq sigpendq_t; + +/* The following defines the queue structure within each TCB to hold queued + * signal actions that need action by the task + */ + +struct sigq_s +{ + FAR struct sigq_s *flink; /* Forward link */ + union + { + void (*sighandler)(int signo, siginfo_t *info, void *context); + } action; /* Signal action */ + sigset_t mask; /* Additional signals to mask while the + * the signal-catching function executes */ + siginfo_t info; /* Signal information */ + uint8_t type; /* (Used to manage allocations) */ +}; +typedef struct sigq_s sigq_t; + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/* The g_sigfreeaction data structure is a list of available signal action + * structures. + */ + +extern sq_queue_t g_sigfreeaction; + +/* The g_sigpendingaction data structure is a list of available pending + * signal action structures. + */ + +extern sq_queue_t g_sigpendingaction; + +/* The g_sigpendingirqaction is a list of available pending signal actions + * that are reserved for use by interrupt handlers. + */ + +extern sq_queue_t g_sigpendingirqaction; + +/* The g_sigpendingsignal data structure is a list of available pending + * signal structures. + */ + +extern sq_queue_t g_sigpendingsignal; + +/* The g_sigpendingirqsignal data structure is a list of available pending + * signal structures that are reserved for use by interrupt handlers. + */ + +extern sq_queue_t g_sigpendingirqsignal; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* Internal signal-related interfaces ***************************************/ + +/* sig_intialize.c */ + +void weak_function sig_initialize(void); +void sig_allocateactionblock(void); + +/* sig_action.c */ + +void sig_releaseaction(FAR sigactq_t *sigact); + +/* sig_pending.c */ + +sigset_t sig_pendingset(FAR _TCB *stcb); + +/* In files of the same name */ + +FAR sigq_t *sig_allocatependingsigaction(void); +void sig_cleanup(FAR _TCB *stcb); +void sig_deliver(FAR _TCB *stcb); +FAR sigactq_t *sig_findaction(FAR _TCB *stcb, int signo); +int sig_lowest(FAR sigset_t *set); +#ifdef CONFIG_CAN_PASS_STRUCTS +int sig_mqnotempty(int tid, int signo, union sigval value); +#else +int sig_mqnotempty(int tid, int signo, FAR void *sival_ptr); +#endif +int sig_received(FAR _TCB *stcb, FAR siginfo_t *info); +void sig_releasependingsigaction(FAR sigq_t *sigq); +void sig_releasependingsignal(FAR sigpendq_t *sigpend); +FAR sigpendq_t *sig_removependingsignal(FAR _TCB *stcb, int signo); +void sig_unmaskpendingsignal(void); + +#endif /* __SCHED_SIG_INTERNAL_H */ diff --git a/nuttx/sched/sig_kill.c b/nuttx/sched/sig_kill.c new file mode 100644 index 000000000..17921015f --- /dev/null +++ b/nuttx/sched/sig_kill.c @@ -0,0 +1,135 @@ +/************************************************************************ + * sched/sig_kill.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include + +#include "os_internal.h" +#include "sig_internal.h" + +/************************************************************************ + * Global Functions + ************************************************************************/ + +/************************************************************************ + * Name: kill + * + * Description: + * The kill() system call can be used to send any signal to any task. + * + * Limitation: Sending of signals to 'process groups' is not + * supported in NuttX + * + * Parameters: + * pid - The id of the task to receive the signal. The POSIX kill + * specification encodes process group information as zero and + * negative pid values. Only positive, non-zero values of pid are + * supported by this implementation. + * signo - The signal number to send. If signo is zero, no signal is + * sent, but all error checking is performed. + * + * Returned Value: + * On success (at least one signal was sent), zero is returned. On + * error, -1 is returned, and errno is set appropriately: + * + * EINVAL An invalid signal was specified. + * EPERM The process does not have permission to send the + * signal to any of the target processes. + * ESRCH The pid or process group does not exist. + * ENOSYS Do not support sending signals to process groups. + * + * Assumptions: + * + ************************************************************************/ + +int kill(pid_t pid, int signo) +{ + FAR _TCB *stcb; + siginfo_t info; + int ret = ERROR; + + /* We do not support sending signals to process groups */ + + if (pid <= 0) + { + errno = ENOSYS; + return ERROR; + } + + /* Make sure that the signal is valid */ + + if (!GOOD_SIGNO(signo)) + { + errno = EINVAL; + return ERROR; + } + + /* Keep things stationary through the following */ + + sched_lock(); + + /* Get the TCB of the receiving task */ + + stcb = sched_gettcb(pid); + sdbg("TCB=0x%08x signo=%d\n", stcb, signo); + if (!stcb) + { + errno = ESRCH; + sched_unlock(); + return ERROR; + } + + /* Create the siginfo structure */ + + info.si_signo = signo; + info.si_code = SI_USER; + info.si_value.sival_ptr = NULL; + + /* Send the signal */ + + ret = sig_received(stcb, &info); + sched_unlock(); + return ret; +} + + diff --git a/nuttx/sched/sig_lowest.c b/nuttx/sched/sig_lowest.c new file mode 100644 index 000000000..f5654eb47 --- /dev/null +++ b/nuttx/sched/sig_lowest.c @@ -0,0 +1,91 @@ +/************************************************************************ + * sched/sig_lowest.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include + +#include "sig_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sig_lowest + * + * Description: + * Return the lowest signal number that is a member of a set of signals. + * + ************************************************************************/ + +int sig_lowest(sigset_t *set) +{ + int signo; + + for (signo = MIN_SIGNO; signo <= MAX_SIGNO; signo++) + { + if (sigismember(set, signo)) + { + return signo; + } + } + + return ERROR; +} diff --git a/nuttx/sched/sig_mqnotempty.c b/nuttx/sched/sig_mqnotempty.c new file mode 100644 index 000000000..9a1fd7243 --- /dev/null +++ b/nuttx/sched/sig_mqnotempty.c @@ -0,0 +1,128 @@ +/**************************************************************************** + * sched/sig_mqnotempty.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include + +#include +#include +#include + +#include "os_internal.h" +#include "sig_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functionss + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sig_mqnotempty + * + * Description: + * This function is equivalent to sigqueue(), but supports the messaging + * system's requirement to signal a task when a message queue becomes + * non-empty. It is identical to sigqueue(), except that it sets the + * si_code field in the siginfo structure to SI_MESGQ rather than SI_QUEUE. + * + ****************************************************************************/ + +#ifdef CONFIG_CAN_PASS_STRUCTS +int sig_mqnotempty (int pid, int signo, union sigval value) +#else +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; +} diff --git a/nuttx/sched/sig_pending.c b/nuttx/sched/sig_pending.c new file mode 100644 index 000000000..eaabbff6b --- /dev/null +++ b/nuttx/sched/sig_pending.c @@ -0,0 +1,130 @@ +/**************************************************************************** + * sched/sig_pending.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include + +#include "os_internal.h" +#include "sig_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sigpending + * + * Description: + * This function stores the returns the set of signals that are blocked + * for delivery and that are pending for the calling process in the space + * pointed to by set. + * + * Parameters: + * set - The location to return the pending signal set. + * + * Return Value: + * 0 (OK) or -1 (ERROR) + * + * Assumptions: + * + ****************************************************************************/ + +int sigpending(FAR sigset_t *set) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + int ret = ERROR; + + if (set) + { + *set = sig_pendingset(rtcb); + ret = OK; + } + + return ret; +} + +/**************************************************************************** + * Name: sig_pendingset + * + * Description: + * Convert the list of pending signals into a signal set + * + ****************************************************************************/ + +sigset_t sig_pendingset(FAR _TCB *stcb) +{ + sigset_t sigpendset; + FAR sigpendq_t *sigpend; + irqstate_t saved_state; + + sigpendset = NULL_SIGNAL_SET; + + saved_state = irqsave(); + for (sigpend = (FAR sigpendq_t*)stcb->sigpendingq.head; + (sigpend); sigpend = sigpend->flink) + { + sigaddset(&sigpendset, sigpend->info.si_signo); + } + + irqrestore(saved_state); + + return sigpendset; +} diff --git a/nuttx/sched/sig_procmask.c b/nuttx/sched/sig_procmask.c new file mode 100644 index 000000000..c67159589 --- /dev/null +++ b/nuttx/sched/sig_procmask.c @@ -0,0 +1,180 @@ +/**************************************************************************** + * sched/sig_procmask.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "os_internal.h" +#include "sig_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sigprocmask + * + * Description: + * This function allows the calling process to examine and/or change its + * signal mask. If the 'set' is not NULL, then it points to a set of + * signals to be used to change the currently blocked set. The value of + * 'how' indicates the manner in which the set is changed. + * + * If there any pending unblocked signals after the call to sigprocmask(), + * those signals will be delivered before sigprocmask() returns. + * + * If sigprocmask() fails, the signal mask of the process is not changed + * by this function call. + * + * Parameters: + * how - How the signal mast will be changed: + * SIG_BLOCK - The resulting set is the union of the current set + * and the signal set pointed to by 'set'. + * SIG_UNBLOCK - The resulting set is the intersection of the current + * set and the complement of the signal set pointed to + * by 'set'. + * SIG_SETMASK - The resulting set is the signal set pointed to by + * 'set'. + * set - Location of the new signal mask + * oset - Location to store the old signal mask + * + * Return Value: + * 0 (OK), or -1 (ERROR) if how is invalid. + * + * Assumptions: + * + ****************************************************************************/ + +int sigprocmask(int how, FAR const sigset_t *set, FAR sigset_t *oset) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + sigset_t oldsigprocmask; + irqstate_t saved_state; + int ret = OK; + + sched_lock(); + + /* Return the old signal mask if requested */ + + oldsigprocmask = rtcb->sigprocmask; + if (oset) + { + *oset = oldsigprocmask; + } + + /* Modify the current signal mask if so requested */ + + if (set) + { + /* Some of these operations are non-atomic. We need to protect + * ourselves from attempts to process signals from interrupts + */ + + saved_state = irqsave(); + + /* Okay, determine what we are supposed to do */ + + switch (how) + { + /* The resulting set is the union of the current set and the + * signal set pointed to by set. + */ + + case SIG_BLOCK: + rtcb->sigprocmask |= *set; + break; + + /* The resulting set is the intersection of the current set and + * the complement of the signal set pointed to by _set. + */ + + case SIG_UNBLOCK: + rtcb->sigprocmask &= ~(*set); + break; + + /* The resulting set is the signal set pointed to by set. */ + + case SIG_SETMASK: + rtcb->sigprocmask = *set; + break; + + default: + ret = ERROR; + break; + } + + irqrestore(saved_state); + + /* Now, process any pending signals that were just unmasked */ + + sig_unmaskpendingsignal(); + } + + sched_unlock(); + return ret; +} diff --git a/nuttx/sched/sig_queue.c b/nuttx/sched/sig_queue.c new file mode 100644 index 000000000..dee1c798a --- /dev/null +++ b/nuttx/sched/sig_queue.c @@ -0,0 +1,159 @@ +/**************************************************************************** + * sched/sig_queue.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include + +#include +#include +#include +#include + +#include "os_internal.h" +#include "sig_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sigqueue + * + * Description: + * This function sends the signal specified by signo with the signal + * parameter value to the process specified by pid. + * + * If the receiving process has the signal blocked via the sigprocmask, + * the signal will pend until it is unmasked. Only one pending signal (per + * signo) is retained. This is consistent with POSIX which states, "If + * a subsequent occurrence of a pending signal is generated, it is + * implementation defined as to whether the signal is delivered more than + * once." + * + * Parameters: + * pid - Process ID of task to receive signal + * signo - Signal number + * value - Value to pass to task with signal + * + * Return Value: + * On success (at least one signal was sent), zero is returned. On + * error, -1 is returned, and errno is set appropriately: + * + * EGAIN The limit of signals which may be queued has been reached. + * EINVAL sig was invalid. + * EPERM The process does not have permission to send the + * signal to the receiving process. + * ESRCH No process has a PID matching pid. + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_CAN_PASS_STRUCTS +int sigqueue (int pid, int signo, union sigval value) +#else +int sigqueue(int pid, int signo, void *sival_ptr) +#endif +{ + FAR _TCB *stcb; + siginfo_t info; + int ret = ERROR; + + /* Sanity checks */ + + if (!GOOD_SIGNO(signo)) + { + set_errno(EINVAL); + return ERROR; + } + + sched_lock(); + + /* Get the TCB of the receiving task */ + + stcb = sched_gettcb(pid); +#ifdef CONFIG_CAN_PASS_STRUCTS + sdbg("TCB=0x%08x signo=%d value=%d\n", stcb, signo, value.sival_int); +#else + sdbg("TCB=0x%08x signo=%d value=%p\n", stcb, signo, sival_ptr); +#endif + if (pid == 0 || !stcb) + { + set_errno(ESRCH); + sched_unlock(); + return ERROR; + } + + /* Create the siginfo structure */ + + info.si_signo = signo; + info.si_code = SI_QUEUE; +#ifdef CONFIG_CAN_PASS_STRUCTS + info.si_value = value; +#else + info.si_value.sival_ptr = sival_ptr; +#endif + + /* Send the signal */ + + ret = sig_received(stcb, &info); + sched_unlock(); + return ret; +} + diff --git a/nuttx/sched/sig_received.c b/nuttx/sched/sig_received.c new file mode 100644 index 000000000..cf4d00165 --- /dev/null +++ b/nuttx/sched/sig_received.c @@ -0,0 +1,404 @@ +/************************************************************************ + * sched/sig_received.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include +#include + +#include + +#include "os_internal.h" +#include "sem_internal.h" +#include "sig_internal.h" +#include "mq_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Name: sig_queueaction + * + * Description: + * Queue a signal action for delivery to a task. + * + ************************************************************************/ + +static int sig_queueaction(FAR _TCB *stcb, siginfo_t *info) +{ + FAR sigactq_t *sigact; + FAR sigq_t *sigq; + irqstate_t saved_state; + int ret = OK; + + sched_lock(); + + /* Find the sigaction associated with this signal */ + + sigact = sig_findaction(stcb, info->si_signo); + + /* Check if a valid signal handler is available and if the signal is + * unblocked. NOTE: There is no default action. + */ + + if ((sigact) && (sigact->act.sa_u._sa_sigaction)) + { + /* Allocate a new element for the signal queue. NOTE: sig_allocatependingsigaction + * will force a system crash if it is unable to allocate memory for the + * signal data */ + + sigq = sig_allocatependingsigaction(); + if (!sigq) ret = ERROR; + else + { + /* Populate the new signal queue element */ + + sigq->action.sighandler = sigact->act.sa_u._sa_sigaction; + sigq->mask = sigact->act.sa_mask; + memcpy(&sigq->info, info, sizeof(siginfo_t)); + + /* Put it at the end of the pending signals list */ + + saved_state = irqsave(); + sq_addlast((FAR sq_entry_t*)sigq, &(stcb->sigpendactionq)); + irqrestore(saved_state); + } + } + + sched_unlock(); + return ret; +} + +/************************************************************************ + * Name: sig_findpendingsignal + * + * Description: + * Find a specified element in the pending signal list + * + ************************************************************************/ + +static FAR sigpendq_t *sig_findpendingsignal(FAR _TCB *stcb, int signo) +{ + FAR sigpendq_t *sigpend = NULL; + irqstate_t saved_state; + + /* Verify the caller's sanity */ + + if (stcb) + { + /* Pending sigals can be added from interrupt level. */ + + saved_state = irqsave(); + + /* Seach the list for a sigpendion on this signal */ + + for(sigpend = (FAR sigpendq_t*)stcb->sigpendingq.head; + (sigpend && sigpend->info.si_signo != signo); + sigpend = sigpend->flink); + irqrestore(saved_state); + } + + return sigpend; +} + +/************************************************************************ + * Name: sig_allocatependingsignal + * + * Description: + * Allocate a pending signal list entry + * + ************************************************************************/ + +static FAR sigpendq_t *sig_allocatependingsignal(void) +{ + FAR sigpendq_t *sigpend; + irqstate_t saved_state; + + /* Check if we were called from an interrupt handler. */ + + if (up_interrupt_context()) + { + /* Try to get the pending signal structure from the free list */ + + sigpend = (FAR sigpendq_t*)sq_remfirst(&g_sigpendingsignal); + if (!sigpend) + { + /* If no pending signal structure is available in the free list, + * then try the special list of structures reserved for + * interrupt handlers + */ + + sigpend = (FAR sigpendq_t*)sq_remfirst(&g_sigpendingirqsignal); + } + } + + /* If we were not called from an interrupt handler, then we are + * free to allocate pending action structures if necessary. */ + + else + { + /* Try to get the pending signal structure from the free list */ + + saved_state = irqsave(); + sigpend = (FAR sigpendq_t*)sq_remfirst(&g_sigpendingsignal); + irqrestore(saved_state); + + /* Check if we got one. */ + + if (!sigpend) + { + /* No... Allocate the pending signal */ + + if (!sigpend) + { + sigpend = (FAR sigpendq_t *)kmalloc((sizeof (sigpendq_t))); + } + + /* Check if we got an allocated message */ + + if (sigpend) + { + sigpend->type = SIG_ALLOC_DYN; + } + } + } + + return sigpend; +} + +/************************************************************************ + * Name: sig_addpendingsignal + * + * Description: + * Add the specified signal to the signal pending list. NOTE: This + * function will queue only one entry for each pending signal. This + * was done intentionally so that a run-away sender cannot consume + * all of memory. + * + ************************************************************************/ + +static FAR sigpendq_t *sig_addpendingsignal(FAR _TCB *stcb, + siginfo_t *info) +{ + FAR sigpendq_t *sigpend; + irqstate_t saved_state; + + /* Check if the signal is already pending */ + + sigpend = sig_findpendingsignal(stcb, info->si_signo); + if (sigpend) + { + /* The signal is already pending... retain only one copy */ + + memcpy(&sigpend->info, info, sizeof(siginfo_t)); + } + + /* No... There is nothing pending for this signo */ + + else + { + /* Allocate a new pending signal entry */ + + sigpend = sig_allocatependingsignal(); + if (sigpend) + { + /* Put the signal information into the allocated structure */ + + memcpy(&sigpend->info, info, sizeof(siginfo_t)); + + /* Add the structure to the pending signal list */ + + saved_state = irqsave(); + sq_addlast((FAR sq_entry_t*)sigpend, &stcb->sigpendingq); + irqrestore(saved_state); + } + } + + return sigpend; +} + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sig_received + * + * Description: + * All signals received the task (whatever the source) go through this + * function to be processed. This function is responsible for: + * + * - Determining if the signal is blocked. + * - Queuing and dispatching signal actions + * - Unblocking tasks that are waiting for signals + * - Queuing pending signals. + * + ************************************************************************/ + +int sig_received(FAR _TCB *stcb, siginfo_t *info) +{ + irqstate_t saved_state; + int ret = ERROR; + + sdbg("TCB=0x%08x signo=%d code=%d value=%d mask=%08x\n", + stcb, info->si_signo, info->si_code, + info->si_value.sival_int, stcb->sigprocmask); + + if (stcb && info) + { + ret = OK; + + /****************** MASKED SIGNAL HANDLING ******************/ + + /* Check if the signal is masked -- if it is, it will be added to the + * list of pending signals. + */ + + if (sigismember(&stcb->sigprocmask, info->si_signo)) + { + /* Check if the task is waiting for this pending signal. If so, + * then unblock it. This must be performed in a critical section + * because signals can be queued from the interrupt level. + */ + + saved_state = irqsave(); + if (stcb->task_state == TSTATE_WAIT_SIG && + sigismember(&stcb->sigwaitmask, info->si_signo)) + { + memcpy(&stcb->sigunbinfo, info, sizeof(siginfo_t)); + stcb->sigwaitmask = NULL_SIGNAL_SET; + up_unblock_task(stcb); + irqrestore(saved_state); + } + + /* Its not one we are waiting for... Add it to the list of pending + * signals. + */ + + else + { + irqrestore(saved_state); + if (!sig_addpendingsignal(stcb, info)) + { + PANIC(OSERR_FAILEDTOADDSIGNAL); + } + } + } + + /****************** UNMASKED SIGNAL HANDLING ******************/ + + else + { + /* Queue any sigaction's requested by this task. */ + + ret = sig_queueaction(stcb, info); + + /* Then schedule execution of the signal handling action on + * the recipients thread. + */ + + up_schedule_sigaction(stcb, sig_deliver); + + /* Check if the task is waiting for an unmasked signal. If so, + * then unblock it. This must be performed in a critical section + * because signals can be queued from the interrupt level. + */ + + saved_state = irqsave(); + if (stcb->task_state == TSTATE_WAIT_SIG) + { + memcpy(&stcb->sigunbinfo, info, sizeof(siginfo_t)); + stcb->sigwaitmask = NULL_SIGNAL_SET; + up_unblock_task(stcb); + } + irqrestore(saved_state); + + /* If the task neither was waiting for the signal nor had a signal + * handler attached to the signal, then the default action is + * simply to ignore the signal + */ + + /****************** OTHER SIGNAL HANDLING ******************/ + + /* If the task is blocked waiting for a semaphore, then that + * task must be unblocked when a signal is received. + */ + + if (stcb->task_state == TSTATE_WAIT_SEM) + { + sem_waitirq(stcb, EINTR); + } + + /* If the task is blocked waiting on a message queue, then that + * task must be unblocked when a signal is received. + */ + +#ifndef CONFIG_DISABLE_MQUEUE + if (stcb->task_state == TSTATE_WAIT_MQNOTEMPTY || + stcb->task_state == TSTATE_WAIT_MQNOTFULL) + { + mq_waitirq(stcb, EINTR); + } +#endif + } + } + + return ret; +} diff --git a/nuttx/sched/sig_releasependingsigaction.c b/nuttx/sched/sig_releasependingsigaction.c new file mode 100644 index 000000000..69252f284 --- /dev/null +++ b/nuttx/sched/sig_releasependingsigaction.c @@ -0,0 +1,120 @@ +/************************************************************************ + * sched/sig_releasependingsigaction.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include + +#include "os_internal.h" +#include "sig_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sig_releasependingsigaction + * + * Description: + * Deallocate a pending signal action Q entry + * + ************************************************************************/ + +void sig_releasependingsigaction(FAR sigq_t *sigq) +{ + irqstate_t saved_state; + + /* If this is a generally available pre-allocated structyre, + * then just put it back in the free list. + */ + + if (sigq->type == SIG_ALLOC_FIXED) + { + /* Make sure we avoid concurrent access to the free + * list from interrupt handlers. */ + + saved_state = irqsave(); + sq_addlast((FAR sq_entry_t*)sigq, &g_sigpendingaction); + irqrestore(saved_state); + } + + /* If this is a message pre-allocated for interrupts, + * then put it back in the correct free list. + */ + + else if (sigq->type == SIG_ALLOC_IRQ) + { + /* Make sure we avoid concurrent access to the free + * list from interrupt handlers. */ + + saved_state = irqsave(); + sq_addlast((FAR sq_entry_t*)sigq, &g_sigpendingirqaction); + irqrestore(saved_state); + } + + /* Otherwise, deallocate it. Note: interrupt handlers + * will never deallocate signals because they will not + * receive them. + */ + + else if (sigq->type == SIG_ALLOC_DYN) + { + sched_free(sigq); + } +} diff --git a/nuttx/sched/sig_releasependingsignal.c b/nuttx/sched/sig_releasependingsignal.c new file mode 100644 index 000000000..5b847bc64 --- /dev/null +++ b/nuttx/sched/sig_releasependingsignal.c @@ -0,0 +1,131 @@ +/************************************************************************ + * sched/sig_releasependingsignal.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "os_internal.h" +#include "sig_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sig_releasependingsignal + * + * Description: + * Deallocate a pending signal list entry + * + ************************************************************************/ + +void sig_releasependingsignal(FAR sigpendq_t *sigpend) +{ + irqstate_t saved_state; + + /* If this is a generally available pre-allocated structyre, + * then just put it back in the free list. + */ + + if (sigpend->type == SIG_ALLOC_FIXED) + { + /* Make sure we avoid concurrent access to the free + * list from interrupt handlers. + */ + + saved_state = irqsave(); + sq_addlast((FAR sq_entry_t*)sigpend, &g_sigpendingsignal); + irqrestore(saved_state); + } + + /* If this is a message pre-allocated for interrupts, + * then put it back in the correct free list. + */ + + else if (sigpend->type == SIG_ALLOC_IRQ) + { + /* Make sure we avoid concurrent access to the free + * list from interrupt handlers. + */ + + saved_state = irqsave(); + sq_addlast((FAR sq_entry_t*)sigpend, &g_sigpendingirqsignal); + irqrestore(saved_state); + } + + /* Otherwise, deallocate it. Note: interrupt handlers + * will never deallocate signals because they will not + * receive them. + */ + + else if (sigpend->type == SIG_ALLOC_DYN) + { + sched_free(sigpend); + } +} diff --git a/nuttx/sched/sig_removependingsignal.c b/nuttx/sched/sig_removependingsignal.c new file mode 100644 index 000000000..c82bf983b --- /dev/null +++ b/nuttx/sched/sig_removependingsignal.c @@ -0,0 +1,115 @@ +/************************************************************************ + * sched/sig_removependingsignal.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "os_internal.h" +#include "sig_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sig_removependingsignal + * + * Description: + * Remove the specified signal from the signal pending list + * + ************************************************************************/ + +FAR sigpendq_t *sig_removependingsignal(FAR _TCB *stcb, int signo) +{ + FAR sigpendq_t *currsig; + FAR sigpendq_t *prevsig; + irqstate_t saved_state; + + saved_state = irqsave(); + + for (prevsig = NULL, currsig = (FAR sigpendq_t*)stcb->sigpendingq.head; + (currsig && currsig->info.si_signo != signo); + prevsig = currsig, currsig = currsig->flink); + + if (currsig) + { + if (prevsig) + { + sq_remafter((FAR sq_entry_t*)prevsig, &stcb->sigpendingq); + } + else + { + sq_remfirst(&stcb->sigpendingq); + } + } + + irqrestore(saved_state); + + return currsig; +} diff --git a/nuttx/sched/sig_suspend.c b/nuttx/sched/sig_suspend.c new file mode 100644 index 000000000..09f47dee9 --- /dev/null +++ b/nuttx/sched/sig_suspend.c @@ -0,0 +1,180 @@ +/**************************************************************************** + * sched/sig_suspend.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include + +#include + +#include "os_internal.h" +#include "sig_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sigsuspend + * + * Description: + * + * The sigsuspend() function replaces the signal mask of the task with the + * set of signals pointed to by the argument 'set' and then suspends the + * process until delivery of a signal to the task. + * + * If the effect of the set argument is to unblock a pending signal, then + * no wait is performed. + * + * The original signal mask is restored when this function returns. + * + * Waiting for an empty signal set stops a task without freeing any + * resources. + * + * Parameters: + * set - signal mask to use while suspended. + * + * Return Value: + * -1 (ERROR) always + * + * Assumptions: + * + * POSIX Compatibility: + * int sigsuspend(const sigset_t *set); + * + * POSIX states that sigsuspend() "suspends the process until delivery of + * a signal whose action is either to execute a signal-catching function + * or to terminate the process." Only the deliver of a signal is required + * in the present implementation (even if the signal is ignored). + * + ****************************************************************************/ + +int sigsuspend(FAR const sigset_t *set) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + sigset_t intersection; + sigset_t saved_sigprocmask; + FAR sigpendq_t *sigpend; + irqstate_t saved_state; + int unblocksigno; + + /* 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! + */ + + sched_lock(); /* Not necessary */ + saved_state = irqsave(); + + /* Check if there is a pending signal corresponding to one of the + * signals that will be unblocked by the new sigprocmask. + */ + + 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. + */ + + unblocksigno = sig_lowest(&intersection); + sigpend = sig_removependingsignal(rtcb, unblocksigno); + if (!sigpend) + { + PANIC(OSERR_FAILEDTOREMOVESIGNAL); + } + + sig_releasependingsignal(sigpend); + irqrestore(saved_state); + } + else + { + /* Its time to wait. Save a copy of the old sigprocmask and install + * the new (temporary) sigprocmask + */ + + saved_sigprocmask = rtcb->sigprocmask; + rtcb->sigprocmask = *set; + rtcb->sigwaitmask = NULL_SIGNAL_SET; + + /* And wait until one of the unblocked signals is posted */ + + up_block_task(rtcb, TSTATE_WAIT_SIG); + + /* We are running again, restore the original sigprocmask */ + + rtcb->sigprocmask = saved_sigprocmask; + irqrestore(saved_state); + + /* Now, handle the (rare?) case where (a) a blocked signal was received + * while the task was suspended but (b) restoring the original + * sigprocmask will unblock the signal. + */ + + sig_unmaskpendingsignal(); + } + + sched_unlock(); + return ERROR; +} diff --git a/nuttx/sched/sig_timedwait.c b/nuttx/sched/sig_timedwait.c new file mode 100644 index 000000000..1b8dfd162 --- /dev/null +++ b/nuttx/sched/sig_timedwait.c @@ -0,0 +1,334 @@ +/**************************************************************************** + * sched/sig_timedwait.c + * + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "os_internal.h" +#include "sig_internal.h" +#include "clock_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* This is a special value of si_signo that means that it was the timeout + * that awakened the wait... not the receipt of a signal. + */ + +#define SIG_WAIT_TIMEOUT 0xff + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functionss + ****************************************************************************/ + +/**************************************************************************** + * Name: sig_timeout + * + * Description: + * A timeout elapsed while waiting for signals to be queued. + * + ****************************************************************************/ + +static void sig_timeout(int argc, uint32_t itcb) +{ + /* On many small machines, pointers are encoded and cannot be simply cast + * from uint32_t to _TCB*. The following union works around this + * (see wdogparm_t). This odd logic could be conditioned on + * CONFIG_CAN_CAST_POINTERS, but it is not too bad in any case. + */ + + union + { + FAR _TCB *wtcb; + uint32_t itcb; + } u; + + u.itcb = itcb; + + if (!u.wtcb) + { + PANIC(OSERR_TIMEOUTNOTCB); + } + + /* There may be a race condition -- make sure the task is + * still waiting for a signal + */ + + if (u.wtcb->task_state == TSTATE_WAIT_SIG) + { + u.wtcb->sigunbinfo.si_signo = SIG_WAIT_TIMEOUT; + u.wtcb->sigunbinfo.si_code = SI_TIMER; + u.wtcb->sigunbinfo.si_value.sival_int = 0; + up_unblock_task(u.wtcb); + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sigtimedwait + * + * Description: + * This function selects the pending signal set specified by the argument + * set. If multiple signals are pending in set, it will remove and return + * the lowest numbered one. If no signals in set are pending at the time + * of the call, the calling process will be suspended until one of the + * signals in set becomes pending, OR until the process is interrupted by + * an unblocked signal, OR until the time interval specified by timeout + * (if any), has expired. If timeout is NULL, then the timeout interval + * is forever. + * + * If the info argument is non-NULL, the selected signal number is stored + * in the si_signo member and the cause of the signal is store in the + * si_code emember. The content of si_value is only meaningful if the + * signal was generated by sigqueue(). + * + * The following values for si_code are defined in signal.h: + * SI_USER - Signal sent from kill, raise, or abort + * SI_QUEUE - Signal sent from sigqueue + * SI_TIMER - Signal is result of timer expiration + * SI_ASYNCIO - Signal is the result of asynch IO completion + * SI_MESGQ - Signal generated by arrival of a message on an + * empty message queue. + * + * Parameters: + * set - The pending signal set. + * info - The returned value + * timeout - The amount of time to wait + * + * Return Value: + * Signal number that cause the wait to be terminated, otherwise -1 (ERROR) + * is returned with errno set to either: + * + * EAGAIN - No signal specified by set was generated within the specified + * timeout period. + * EINTR - The wait was interrupted by an unblocked, caught signal. + * + * Assumptions: + * + ****************************************************************************/ + +int sigtimedwait(FAR const sigset_t *set, FAR struct siginfo *info, + FAR const struct timespec *timeout) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + sigset_t intersection; + FAR sigpendq_t *sigpend; + WDOG_ID wdog; + irqstate_t saved_state; + int32_t waitticks; + int ret = ERROR; + + 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)); + if (!sigpend) + { + PANIC(OSERR_NOPENDINGSIGNAL); + } + + /* 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 = 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 milliseconds */ + + waitticks = MSEC2TICK(timeout->tv_sec * MSEC_PER_SEC + + timeout->tv_nsec / NSEC_PER_MSEC); + + /* Create a watchdog */ + + wdog = wd_create(); + if (wdog) + { + /* This little 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(wdog, 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(wdog); + } + } + + /* 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; +} diff --git a/nuttx/sched/sig_unmaskpendingsignal.c b/nuttx/sched/sig_unmaskpendingsignal.c new file mode 100644 index 000000000..a7bcc7a29 --- /dev/null +++ b/nuttx/sched/sig_unmaskpendingsignal.c @@ -0,0 +1,138 @@ +/************************************************************************ + * sched/sig_unmaskpendingsignal.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include + +#include "os_internal.h" +#include "sig_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Function Prototypes + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: sig_unmaskpendingsignal + * + * Description: + * Based upon the current setting of the sigprocmask, this function + * unmasks and processes any pending signals. This function should + * be called whenever the sigprocmask is changed. + * + ************************************************************************/ + +void sig_unmaskpendingsignal(void) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + sigset_t unmaskedset; + FAR sigpendq_t *pendingsig; + int signo; + + /* Prohibit any context switches until we are done with this. + * We may still be performing signal operations from interrupt + * handlers, however, none of the pending signals that we + * are concerned with here should be effected. + */ + + sched_lock(); + + /* Get the set of pending signals that were just unmasked. The + * following operation should be safe because the sigprocmask + * can only be changed on this thread of execution. + */ + + unmaskedset = ~(rtcb->sigprocmask) & sig_pendingset(rtcb); + + /* Loop while there are unmasked pending signals to be processed. */ + + while (unmaskedset != NULL_SIGNAL_SET) + { + /* Pending signals will be processed from lowest numbered signal + * to highest + */ + + signo = sig_lowest(&unmaskedset); + if (signo != ERROR) + { + /* Remove the signal from the set of unmasked signals. NOTE: + * this implicitly assumes that only one instance for a given + * signal number is pending. + */ + + sigdelset(&unmaskedset, signo); + + /* Remove the pending signal from the list of pending signals */ + + if ((pendingsig = sig_removependingsignal(rtcb, signo)) != NULL) + { + /* If there is one, then process it like a normal signal */ + + sig_received(rtcb, &pendingsig->info); + + /* Then remove it from the pending signal list */ + + sig_releasependingsignal(pendingsig); + } + } + } + + sched_unlock(); +} + diff --git a/nuttx/sched/sig_waitinfo.c b/nuttx/sched/sig_waitinfo.c new file mode 100644 index 000000000..0172ec47d --- /dev/null +++ b/nuttx/sched/sig_waitinfo.c @@ -0,0 +1,89 @@ +/**************************************************************************** + * sched/sig_waitinfo.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sigwaitinfo + * + * Description: + * This function is equivalent to sigtimedwait with a NULL timeout + * parameter. + * + * Parameters: + * set - The pending signal set + * info - The returned value + * + * Return Value: + * Signal number that cause the wait to be terminated, otherwise -1 (ERROR) + * is returned. + * + * Assumptions: + * + ****************************************************************************/ + +int sigwaitinfo(FAR const sigset_t *set, FAR struct siginfo *info) +{ + return sigtimedwait(set, info, NULL); +} diff --git a/nuttx/sched/sleep.c b/nuttx/sched/sleep.c new file mode 100644 index 000000000..03884a5b6 --- /dev/null +++ b/nuttx/sched/sleep.c @@ -0,0 +1,196 @@ +/**************************************************************************** + * sched/sleep.c + * + * Copyright (C) 2007, 2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include + +#include +#include + +/**************************************************************************** + * Preprocessor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Definitions + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sleep + * + * Description: + * The sleep() function will cause the calling thread to be suspended from + * execution until either the number of real-time seconds specified by the + * argument 'seconds' has elapsed or a signal is delivered to the calling + * thread and its action is to invoke a signal-catching function or to + * terminate the process. The suspension time may be longer than requested + * due to the scheduling of other activity by the system. + * + * If a SIGALRM signal is generated for the calling process during + * execution of sleep() and if the SIGALRM signal is being ignored or + * blocked from delivery, it is unspecified whether sleep() returns + * when the SIGALRM signal is scheduled. If the signal is being blocked, it + * is also unspecified whether it remains pending after sleep() returns or + * it is discarded. + * + * If a SIGALRM signal is generated for the calling process during + * execution of sleep(), except as a result of a prior call to alarm(), + * and if the SIGALRM signal is not being ignored or blocked from delivery, + * it is unspecified whether that signal has any effect other than causing + * sleep() to return. + * + * If a signal-catching function interrupts sleep() and examines or changes + * either the time a SIGALRM is scheduled to be generated, the action + * associated with the SIGALRM signal, or whether the SIGALRM signal is + * blocked from delivery, the results are unspecified. + * + * If a signal-catching function interrupts sleep() and calls siglongjmp() + * or longjmp() to restore an environment saved prior to the sleep() call, + * the action associated with the SIGALRM signal and the time at which a + * SIGALRM signal is scheduled to be generated are unspecified. It is also + * unspecified whether the SIGALRM signal is blocked, unless the process' + * signal mask is restored as part of the environment. + * + * Implementations may place limitations on the granularity of timer values. + * For each interval timer, if the requested timer value requires a finer + * granularity than the implementation supports, the actual timer value will + * be rounded up to the next supported value. + * + * Interactions between sleep() and any of setitimer(), ualarm() or sleep() + * are unspecified. + * + * Parameters: + * seconds + * + * Returned Value: + * If sleep() returns because the requested time has elapsed, the value + * returned will be 0. If sleep() returns because of premature arousal due + * to delivery of a signal, the return value will be the "unslept" amount + * (the requested time minus the time actually slept) in seconds. + * + * Assumptions: + * + ****************************************************************************/ + +unsigned int sleep(unsigned int seconds) +{ + sigset_t set; + struct timespec ts; + struct siginfo value; + irqstate_t flags; + uint32_t start; + int32_t elapsed; + int32_t remaining = 0; + + /* Don't sleep if seconds == 0 */ + + if (seconds) + { + /* Set up for the sleep. Using the empty set means that we are not + * waiting for any particualar signal. However, any unmasked signal + * can still awaken sigtimedwait(). + */ + + (void)sigemptyset(&set); + ts.tv_sec = seconds; + ts.tv_nsec = 0; + + /* Interrupts are disabled around the following so that it is atomic */ + + flags = irqsave(); + + /* Get the current time then sleep for the requested time. + * 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. + */ + + start = clock_systimer(); + (void)sigtimedwait(&set, &value, &ts); + + /* Calculate the elapsed time (in clock ticks) when we wake up from the sleep. + * This is really only necessary if we were awakened from the sleep early + * due to the receipt of a signal. + */ + + elapsed = clock_systimer() - start; + irqrestore(flags); + + /* Get the remaining, un-waited seconds. Note that this calculation + * truncates the elapsed seconds in the division. We may have slept some + * fraction of a second longer than this! But if the calculation is less + * than the 'seconds', we certainly did not sleep for the complete + * requested interval. + */ + + remaining = (int32_t)seconds - elapsed / TICK_PER_SEC; + + /* Make sure that the elapsed time is non-negative (this should always + * be the case unless something exceptional happened while were we + * sleeping -- like the clock was reset or we went into a low power mode, + * OR if we had to wait a long time to run again after calling + * sigtimedwait() making 'elapsed' bigger than it should have been). + */ + + if (remaining < 0) + { + remaining = 0; + } + } + + return (unsigned int)remaining; +} diff --git a/nuttx/sched/task_activate.c b/nuttx/sched/task_activate.c new file mode 100644 index 000000000..bae2856a1 --- /dev/null +++ b/nuttx/sched/task_activate.c @@ -0,0 +1,117 @@ +/**************************************************************************** + * sched/task_activate.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include + +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: task_activate + * + * Description: + * This function activates tasks initialized by task_schedsetup(). Without + * activation, a task is ineligible for execution by the scheduler. + * + * Input Parameters: + * tcb - The TCB for the task for the task (same as the task_init argument). + * + * Return Value: + * Always returns OK + * + ****************************************************************************/ + +int task_activate(FAR _TCB *tcb) +{ + irqstate_t flags = irqsave(); + +#ifdef CONFIG_SCHED_INSTRUMENTATION + + /* Check if this is really a re-start */ + + if (tcb->task_state != TSTATE_TASK_INACTIVE) + { + /* Inform the instrumentation layer that the task + * has stopped + */ + + sched_note_stop(tcb); + } + + /* Inform the instrumentation layer that the task + * has started + */ + + sched_note_start(tcb); +#endif + + up_unblock_task(tcb); + irqrestore(flags); + return OK; +} diff --git a/nuttx/sched/task_create.c b/nuttx/sched/task_create.c new file mode 100644 index 000000000..4d92c9bb0 --- /dev/null +++ b/nuttx/sched/task_create.c @@ -0,0 +1,269 @@ +/**************************************************************************** + * sched/task_create.c + * + * Copyright (C) 2007-2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include + +#include +#include + +#include "os_internal.h" +#include "env_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: thread_create + * + * Description: + * This function creates and activates a new thread of the specified type + * with a specified priority and returns its system-assigned ID. It is the + * internal, commn implementation of task_create() and kernel_thread(). + * See comments with task_create() for further information. + * + * Input Parameters: + * name - Name of the new task + * type - Type of the new task + * priority - Priority of the new task + * stack_size - size (in bytes) of the stack needed + * entry - Entry point of a new task + * arg - A pointer to an array of input parameters. Up to + * CONFIG_MAX_TASK_ARG parameters may be provided. If fewer + * than CONFIG_MAX_TASK_ARG parameters are passed, the list + * should be terminated with a NULL argv[] value. If no + * parameters are required, argv may be NULL. + * + * Return Value: + * Returns the non-zero process ID of the new task or ERROR if memory is + * insufficient or the task cannot be created. The errno will be set to + * indicate the nature of the error (always ENOMEM). + * + ****************************************************************************/ + +#ifndef CONFIG_CUSTOM_STACK +static int thread_create(const char *name, uint8_t type, int priority, + int stack_size, main_t entry, const char **argv) +#else +static int thread_create(const char *name, uint8_t type, int priority, + main_t entry, const char **argv) +#endif +{ + FAR _TCB *tcb; + pid_t pid; + int ret; + + /* Allocate a TCB for the new task. */ + + tcb = (FAR _TCB*)kzalloc(sizeof(_TCB)); + if (!tcb) + { + goto errout; + } + + /* Associate file descriptors with the new task */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0 + ret = sched_setuptaskfiles(tcb); + if (ret != OK) + { + goto errout_with_tcb; + } +#endif + + /* Clone the parent's task environment */ + + (void)env_dup(tcb); + + /* Allocate the stack for the TCB */ + +#ifndef CONFIG_CUSTOM_STACK + ret = up_create_stack(tcb, stack_size); + if (ret != OK) + { + goto errout_with_tcb; + } +#endif + + /* Mark the type of this thread (this setting will be needed in + * task_schedsetup() when up_initial_state() is called. + */ + + tcb->flags |= type; + + /* Initialize the task control block */ + + ret = task_schedsetup(tcb, priority, task_start, entry); + if (ret != OK) + { + goto errout_with_tcb; + } + + /* Setup to pass parameters to the new task */ + + (void)task_argsetup(tcb, name, argv); + + /* Get the assigned pid before we start the task */ + + pid = (int)tcb->pid; + + /* Activate the task */ + + ret = task_activate(tcb); + if (ret != OK) + { + dq_rem((FAR dq_entry_t*)tcb, (dq_queue_t*)&g_inactivetasks); + goto errout_with_tcb; + } + + return pid; + +errout_with_tcb: + sched_releasetcb(tcb); + +errout: + errno = ENOMEM; + return ERROR; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: task_create + * + * Description: + * This function creates and activates a new task with a specified + * priority and returns its system-assigned ID. + * + * The entry address entry is the address of the "main" function of the + * task. This function will be called once the C environment has been + * set up. The specified function will be called with four arguments. + * Should the specified routine return, a call to exit() will + * automatically be made. + * + * Note that four (and only four) arguments must be passed for the spawned + * functions. + * + * Input Parameters: + * name - Name of the new task + * priority - Priority of the new task + * stack_size - size (in bytes) of the stack needed + * entry - Entry point of a new task + * arg - A pointer to an array of input parameters. Up to + * CONFIG_MAX_TASK_ARG parameters may be provided. If fewer + * than CONFIG_MAX_TASK_ARG parameters are passed, the list + * should be terminated with a NULL argv[] value. If no + * parameters are required, argv may be NULL. + * + * Return Value: + * Returns the non-zero process ID of the new task or ERROR if memory is + * insufficient or the task cannot be created. The errno will be set to + * indicate the nature of the error (always ENOMEM). + * + ****************************************************************************/ + +#ifndef CONFIG_CUSTOM_STACK +int task_create(const char *name, int priority, + int stack_size, main_t entry, const char *argv[]) +#else +int task_create(const char *name, int priority, + main_t entry, const char *argv[]) +#endif +{ +#ifndef CONFIG_CUSTOM_STACK + return thread_create(name, TCB_FLAG_TTYPE_TASK, priority, stack_size, entry, argv); +#else + return thread_create(name, TCB_FLAG_TTYPE_TASK, priority, entry, argv); +#endif +} + +/**************************************************************************** + * Name: kernel_thread + * + * Description: + * This function creates and activates a kernel thread task with kernel- + * mode privileges. It is identical to task_create() except that it + * configures the newly started thread to run in kernel model. + * + * Input Parameters: + * (same as task_create()) + * + * Return Value: + * (same as task_create()) + * + ****************************************************************************/ + +#ifndef CONFIG_CUSTOM_STACK +int kernel_thread(const char *name, int priority, + int stack_size, main_t entry, const char *argv[]) +#else +int kernel_thread(const char *name, int priority, + main_t entry, const char *argv[]) +#endif +{ +#ifndef CONFIG_CUSTOM_STACK + return thread_create(name, TCB_FLAG_TTYPE_KERNEL, priority, stack_size, entry, argv); +#else + return thread_create(name, TCB_FLAG_TTYPE_KERNEL, priority, entry, argv); +#endif +} + diff --git a/nuttx/sched/task_delete.c b/nuttx/sched/task_delete.c new file mode 100644 index 000000000..ea0e251db --- /dev/null +++ b/nuttx/sched/task_delete.c @@ -0,0 +1,194 @@ +/**************************************************************************** + * sched/task_delete.c + * + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include + +#include "os_internal.h" +#ifndef CONFIG_DISABLE_SIGNALS +# include "sig_internal.h" +#endif + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: task_delete + * + * Description: + * This function causes a specified task to cease to exist. Its stack and + * TCB will be deallocated. This function is the companion to task_create(). + * + * The logic in this function only deletes non-running tasks. If the 'pid' + * parameter refers to to the currently runing task, then processing is + * redirected to exit(). + * + * Control will still be returned to task_delete() after the exit() logic + * finishes. In fact, this function is the final function called all task + * termination sequences. Here are all possible exit scenarios: + * + * - pthread_exit(). Calls exit() + * - exit(). Calls _exit() + * - _exit(). Calls task_deletecurrent() making the currently running task + * non-running then calls task_delete() to terminate the non-running + * task. + * - task_delete() + * + * Inputs: + * pid - The task ID of the task to delete. A pid of zero + * signifies the calling task. + * + * Return Value: + * OK on success; or ERROR on failure + * + * This function can fail if the provided pid does not correspond to a + * task (errno is not set) + * + ****************************************************************************/ + +int task_delete(pid_t pid) +{ + FAR _TCB *rtcb; + FAR _TCB *dtcb; + irqstate_t saved_state; + int ret = ERROR; + + /* Check if the task to delete is the calling task */ + + rtcb = (FAR _TCB*)g_readytorun.head; + if (pid == 0 || pid == rtcb->pid) + { + /* If it is, then what we really wanted to do was exit. Note that we + * don't bother to unlock the TCB since it will be going away. + */ + + exit(EXIT_SUCCESS); + } + + /* Make sure the task does not become ready-to-run while we are futzing with + * its TCB by locking ourselves as the executing task. + */ + + sched_lock(); + + /* Find for the TCB associated with matching pid */ + + dtcb = sched_gettcb(pid); + if (!dtcb) + { + /* This pid does not correspond to any known task */ + + sched_unlock(); + return ERROR; + } + + /* Verify our internal sanity */ + + if (dtcb->task_state == TSTATE_TASK_RUNNING || + dtcb->task_state >= NUM_TASK_STATES) + { + sched_unlock(); + PANIC(OSERR_BADDELETESTATE); + } + + /* Perform common task termination logic (flushing streams, calling + * functions registered by at_exit/on_exit, etc.). We need to do + * this as early as possible so that higher level clean-up logic + * can run in a healthy tasking environment. + * + * In the case where the task exits via exit(), task_exithook() + * may be called twice. + * + * I suppose EXIT_SUCCESS is an appropriate return value??? + */ + + task_exithook(dtcb, EXIT_SUCCESS); + + /* Remove the task from the OS's tasks lists. */ + + saved_state = irqsave(); + dq_rem((FAR dq_entry_t*)dtcb, (dq_queue_t*)g_tasklisttable[dtcb->task_state].list); + dtcb->task_state = TSTATE_TASK_INVALID; + irqrestore(saved_state); + + /* At this point, the TCB should no longer be accessible to the system */ + + sched_unlock(); + + /* Since all tasks pass through this function as the final step in their + * exit sequence, this is an appropriate place to inform any instrumentation + * layer that the task no longer exists. + */ + + sched_note_stop(dtcb); + + /* Deallocate its TCB */ + + sched_releasetcb(dtcb); + return ret; +} + diff --git a/nuttx/sched/task_deletecurrent.c b/nuttx/sched/task_deletecurrent.c new file mode 100644 index 000000000..77025f5e0 --- /dev/null +++ b/nuttx/sched/task_deletecurrent.c @@ -0,0 +1,140 @@ +/**************************************************************************** + * sched/task_deletecurrent.c + * + * Copyright (C) 2008-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include "os_internal.h" +#ifndef CONFIG_DISABLE_SIGNALS +# include "sig_internal.h" +#endif + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: task_delete + * + * Description: + * This function causes the currently running task (i.e., the task at the + * head of the ready-to-run list) to cease to exist. This is a part of + * the logic used to implement _exit(). The full implementation of _exit() + * is architecture-dependent. This function should never be called from + * normal user code, but only from the architecture-specific implementation + * of exit. + * + * Inputs: + * None + * + * Return Value: + * OK on success; or ERROR on failure + * + ****************************************************************************/ + +int task_deletecurrent(void) +{ + FAR _TCB *dtcb = (FAR _TCB*)g_readytorun.head; + FAR _TCB *rtcb; + + /* Remove the TCB of the current task from the ready-to-run list. A context + * switch will definitely be necessary -- that must be done by the + * architecture-specific logic. + * + * sched_removereadytorun will mark the task at the head of the ready-to-run + * with state == TSTATE_TASK_RUNNING + */ + + (void)sched_removereadytorun(dtcb); + rtcb = (FAR _TCB*)g_readytorun.head; + + /* We are not in a bad state -- the head of the ready to run task list + * does not correspond to the thread that is running. Disabling pre- + * emption on this TCB and marking the new ready-to-run task as not + * running (see, for example, get_errno_ptr()). + */ + + sched_lock(); + rtcb->task_state = TSTATE_TASK_READYTORUN; + + /* Move the TCB to the specified blocked task list and delete it */ + + sched_addblocked(dtcb, TSTATE_TASK_INACTIVE); + task_delete(dtcb->pid); + rtcb->task_state = TSTATE_TASK_RUNNING; + + /* If there are any pending tasks, then add them to the ready-to-run + * task list now + */ + + if (g_pendingtasks.head) + { + (void)sched_mergepending(); + } + + /* Now calling sched_unlock() should have no effect */ + + sched_unlock(); + return OK; +} + diff --git a/nuttx/sched/task_exithook.c b/nuttx/sched/task_exithook.c new file mode 100644 index 000000000..e94476f2a --- /dev/null +++ b/nuttx/sched/task_exithook.c @@ -0,0 +1,290 @@ +/**************************************************************************** + * sched/task_exithook.c + * + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include + +#include +#include + +#include "os_internal.h" +#include "sig_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: task_atexit + * + * Description: + * Call any registerd atexit function(s) + * + ****************************************************************************/ + +#ifdef CONFIG_SCHED_ATEXIT +static inline void task_atexit(FAR _TCB *tcb) +{ +#if defined(CONFIG_SCHED_ATEXIT_MAX) && CONFIG_SCHED_ATEXIT_MAX > 1 + int index; + + /* Call each atexit function in reverse order of registration atexit() + * functions are registered from lower to higher arry indices; they must + * be called in the reverse order of registration when task exists, i.e., + * from higher to lower indices. + */ + + for (index = CONFIG_SCHED_ATEXIT_MAX-1; index >= 0; index--) + { + if (tcb->atexitfunc[index]) + { + /* Call the atexit function */ + + (*tcb->atexitfunc[index])(); + + /* Nullify the atexit function. task_exithook may be called more then + * once in most task exit scenarios. Nullifying the atext function + * pointer will assure that the callback is performed only once. + */ + + tcb->atexitfunc[index] = NULL; + } + } + +#else + if (tcb->atexitfunc) + { + /* Call the atexit function */ + + (*tcb->atexitfunc)(); + + /* Nullify the atexit function. task_exithook may be called more then + * once in most task exit scenarios. Nullifying the atext function + * pointer will assure that the callback is performed only once. + */ + + tcb->atexitfunc = NULL; + } +#endif +#else +# define task_atexit(tcb) +#endif + +/**************************************************************************** + * Name: task_onexit + * + * Description: + * Call any registerd on)exit function(s) + * + ****************************************************************************/ + +#ifdef CONFIG_SCHED_ONEXIT +static inline void task_onexit(FAR _TCB *tcb, int status) +{ +#if defined(CONFIG_SCHED_ONEXIT_MAX) && CONFIG_SCHED_ONEXIT_MAX > 1 + int index; + + /* Call each on_exit function in reverse order of registration. on_exit() + * functions are registered from lower to higher arry indices; they must + * be called in the reverse order of registration when task exists, i.e., + * from higher to lower indices. + */ + + for (index = CONFIG_SCHED_ONEXIT_MAX-1; index >= 0; index--) + { + if (tcb->onexitfunc[index]) + { + /* Call the on_exit function */ + + (*tcb->onexitfunc[index])(status, tcb->onexitarg[index]); + + /* Nullify the on_exit function. task_exithook may be called more then + * once in most task exit scenarios. Nullifying the atext function + * pointer will assure that the callback is performed only once. + */ + + tcb->onexitfunc[index] = NULL; + } + } +#else + if (tcb->onexitfunc) + { + /* Call the on_exit function */ + + (*tcb->onexitfunc)(status, tcb->onexitarg); + + /* Nullify the on_exit function. task_exithook may be called more then + * once in most task exit scenarios. Nullifying the on_exit function + * pointer will assure that the callback is performed only once. + */ + + tcb->onexitfunc = NULL; + } +#endif +} +#else +# define task_onexit(tcb,status) +#endif + +/**************************************************************************** + * Name: task_exitwakeup + * + * Description: + * Wakeup any tasks waiting for this task to exit + * + ****************************************************************************/ + +#ifdef CONFIG_SCHED_WAITPID +static inline void task_exitwakeup(FAR _TCB *tcb, int status) +{ + /* Wakeup any tasks waiting for this task to exit */ + + while (tcb->exitsem.semcount < 0) + { + /* "If more than one thread is suspended in waitpid() awaiting + * termination of the same process, exactly one thread will return + * the process status at the time of the target process termination." + * Hmmm.. what do we return to the others? + */ + + if (tcb->stat_loc) + { + *tcb->stat_loc = status << 8; + tcb->stat_loc = NULL; + } + + /* Wake up the thread */ + + sem_post(&tcb->exitsem); + } +} +#else +# define task_exitwakeup(tcb, status) +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: task_hook + * + * Description: + * This function implements some of the internal logic of exit() and + * task_delete(). This function performs some cleanup and other actions + * required when a task exists: + * + * - All open streams are flushed and closed. + * - All functions registered with atexit() and on_exit() are called, in + * the reverse order of their registration. + * + * When called from exit(), the tcb still resides at the head of the ready- + * to-run list. The following logic is safe because we will not be + * returning from the exit() call. + * + * When called from task_delete() we are operating on a different thread; + * on the thread that called task_delete(). In this case, task_delete + * will have already removed the tcb from the ready-to-run list to prevent + * any further action on this task. + * + ****************************************************************************/ + +void task_exithook(FAR _TCB *tcb, int status) +{ + /* If exit function(s) were registered, call them now before we do any un- + * initialization. NOTE: In the case of task_delete(), the exit function + * will *not* be called on the thread execution of the task being deleted! + */ + + task_atexit(tcb); + + /* Call any registered on_exit function(s) */ + + task_onexit(tcb, status); + + /* Wakeup any tasks waiting for this task to exit */ + + task_exitwakeup(tcb, status); + + /* Flush all streams (File descriptors will be closed when + * the TCB is deallocated). + */ + +#if CONFIG_NFILE_STREAMS > 0 + (void)lib_flushall(tcb->streams); +#endif + + /* Free all file-related resources now. This gets called again + * just be be certain when the TCB is delallocated. However, we + * really need to close files as soon as possible while we still + * have a functioning task. + */ + + (void)sched_releasefiles(tcb); + + /* Deallocate anything left in the TCB's queues */ + +#ifndef CONFIG_DISABLE_SIGNALS + sig_cleanup(tcb); /* Deallocate Signal lists */ +#endif +} diff --git a/nuttx/sched/task_init.c b/nuttx/sched/task_init.c new file mode 100644 index 000000000..31fc5ef70 --- /dev/null +++ b/nuttx/sched/task_init.c @@ -0,0 +1,154 @@ +/**************************************************************************** + * sched/task_init.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include + +#include "os_internal.h" +#include "env_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: task_init + * + * Description: + * This function initializes a Task Control Block (TCB) in preparation for + * starting a new thread. It performs a subset of the functionality of + * task_create() + * + * Unlike task_create(): + * 1. Allocate the TCB. The pre-allocated TCB is passed in the arguments. + * 2. Allocate the stack. The pre-allocated stack is passed in the arguments. + * 3. Activate the task. This must be done by calling task_activate(). + * + * Input Parameters: + * tcb - Address of the new task's TCB + * name - Name of the new task (not used) + * priority - Priority of the new task + * stack - Start of the pre-allocated stack + * stack_size - Size (in bytes) of the stack allocated + * entry - Application start point of the new task + * arg - A pointer to an array of input parameters. Up to + * CONFIG_MAX_TASK_ARG parameters may be provided. If fewer + * than CONFIG_MAX_TASK_ARG parameters are passed, the list + * should be terminated with a NULL argv[] value. If no + * parameters are required, argv may be NULL. + * + * Return Value: + * OK on success; ERROR on failure. (See task_schedsetup() for possible + * failure conditions). On failure, the caller is responsible for freeing + * the stack memory and for calling sched_releasetcb() to free the TCB + * (which could be in most any state). + * + ****************************************************************************/ + +#ifndef CONFIG_CUSTOM_STACK +int task_init(FAR _TCB *tcb, const char *name, int priority, + FAR uint32_t *stack, uint32_t stack_size, + main_t entry, const char *argv[]) +#else +int task_init(FAR _TCB *tcb, const char *name, int priority, + main_t entry, const char *argv[]) +#endif +{ + int ret; + + /* Associate file descriptors with the new task */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0 + if (sched_setuptaskfiles(tcb) != OK) + { + return ERROR; + } +#endif + + /* Clone the parent's task environment */ + + (void)env_dup(tcb); + + /* Configure the user provided stack region */ + +#ifndef CONFIG_CUSTOM_STACK + up_use_stack(tcb, stack, stack_size); +#endif + + /* Initialize the task control block */ + + ret = task_schedsetup(tcb, priority, task_start, entry); + if (ret == OK) + { + /* Setup to pass parameters to the new task */ + + (void)task_argsetup(tcb, name, argv); + } + + return ret; +} + diff --git a/nuttx/sched/task_restart.c b/nuttx/sched/task_restart.c new file mode 100644 index 000000000..6d9b84917 --- /dev/null +++ b/nuttx/sched/task_restart.c @@ -0,0 +1,184 @@ +/**************************************************************************** + * sched/task_restart.c + * + * Copyright (C) 2007, 2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include +#include +#include +#include "os_internal.h" +#include "sig_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: task_restart + * + * Description: + * This function "restarts" a task. The task is first terminated and then + * reinitialized with same ID, priority, original entry point, stack size, + * and parameters it had when it was first started. + * + * Inputs: + * pid - The task ID of the task to delete. An ID of zero signifies the + * calling task. + * + * Return Value: + * OK on sucess; ERROR on failure. + * + * This function can fail if: + * (1) A pid of zero or the pid of the calling task is provided + * (functionality not implemented) + * (2) The pid is not associated with any task known to the system. + * + ****************************************************************************/ + +int task_restart(pid_t pid) +{ + FAR _TCB *rtcb; + FAR _TCB *tcb; + int status; + irqstate_t state; + + /* Make sure this task does not become ready-to-run while + * we are futzing with its TCB + */ + + sched_lock(); + + /* Check if the task to restart is the calling task */ + + rtcb = (FAR _TCB*)g_readytorun.head; + if ((pid == 0) || (pid == rtcb->pid)) + { + /* Not implemented */ + + return ERROR; + } + + /* We are restarting some other task than ourselves */ + + else + { + /* Find for the TCB associated with matching pid */ + + tcb = sched_gettcb(pid); + if (!tcb) + { + /* There is no TCB with this pid */ + + return ERROR; + } + + /* Remove the TCB from whatever list it is in. At this point, the + * TCB should no longer be accessible to the system + */ + + state = irqsave(); + dq_rem((FAR dq_entry_t*)tcb, (dq_queue_t*)g_tasklisttable[tcb->task_state].list); + tcb->task_state = TSTATE_TASK_INVALID; + irqrestore(state); + + /* Deallocate anything left in the TCB's queues */ + + sig_cleanup(tcb); /* Deallocate Signal lists */ + + /* Reset the current task priority */ + + tcb->sched_priority = tcb->init_priority; + + /* Reset the base task priority and the number of pending reprioritizations */ + +#ifdef CONFIG_PRIORITY_INHERITANCE + tcb->base_priority = tcb->init_priority; +# if CONFIG_SEM_NNESTPRIO > 0 + tcb->npend_reprio = 0; +# endif +#endif + + /* Re-initialize the processor-specific portion of the TCB + * This will reset the entry point and the start-up parameters + */ + + up_initial_state(tcb); + + /* Add the task to the inactive task list */ + + dq_addfirst((FAR dq_entry_t*)tcb, (dq_queue_t*)&g_inactivetasks); + tcb->task_state = TSTATE_TASK_INACTIVE; + + /* Activate the task */ + + status = task_activate(tcb); + if (status != OK) + { + dq_rem((FAR dq_entry_t*)tcb, (dq_queue_t*)&g_inactivetasks); + sched_releasetcb(tcb); + return ERROR; + } + } + + sched_unlock(); + return OK; +} diff --git a/nuttx/sched/task_setup.c b/nuttx/sched/task_setup.c new file mode 100644 index 000000000..a37fb165a --- /dev/null +++ b/nuttx/sched/task_setup.c @@ -0,0 +1,347 @@ +/**************************************************************************** + * sched/task_setup.c + * + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include +#include + +#include + +#include "os_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/* This is the name for un-named tasks */ + +static const char g_noname[] = ""; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int task_assignpid(FAR _TCB* tcb); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: task_assignpid + * + * Description: + * This function assigns the next unique task ID to a task. + * + * Inputs: + * tcb - TCB of task + * + * Return: + * OK on success; ERROR on failure (errno is not set) + * + ****************************************************************************/ + +static int task_assignpid(FAR _TCB *tcb) +{ + pid_t next_pid; + int hash_ndx; + int tries; + + /* Disable pre-emption. This should provide sufficient protection + * for the following operation. + */ + + (void)sched_lock(); + + /* We'll try every allowable pid */ + + for (tries = 0; tries < CONFIG_MAX_TASKS; tries++) + { + /* Get the next process ID candidate */ + + next_pid = ++g_lastpid; + + /* Verify that the next_pid is in the valid range */ + + if (next_pid <= 0) + { + g_lastpid = 1; + next_pid = 1; + } + + /* Get the hash_ndx associated with the next_pid */ + + hash_ndx = PIDHASH(next_pid); + + /* Check if there is a (potential) duplicate of this pid */ + + if (!g_pidhash[hash_ndx].tcb) + { + g_pidhash[hash_ndx].tcb = tcb; + g_pidhash[hash_ndx].pid = next_pid; + tcb->pid = next_pid; + (void)sched_unlock(); + return OK; + } + } + + /* If we get here, then the g_pidhash[] table is completely full. + * We cannot allow another task to be started. + */ + + (void)sched_unlock(); + return ERROR; +} + +/**************************************************************************** + * Name: task_dupdspace + * + * Description: + * When a new task or thread is created from a PIC module, then that + * module (probably) intends the task or thread to execute in the same + * D-Space. This function will duplicate the D-Space for that purpose. + * + * Parameters: + * tcb - The TCB of the new task. + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_PIC +static inline void task_dupdspace(FAR _TCB *tcb) +{ + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; + if (rtcb->dspace != NULL) + { + /* Copy the D-Space structure reference and increment the reference + * count on the memory. The D-Space memory will persist until the + * last thread exits (see sched_releasetcb()). + */ + + tcb->dspace = rtcb->dspace; + tcb->dspace->crefs++; + } +} +#else +# define task_dupdspace(tcb) +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: task_schedsetup + * + * Description: + * This functions initializes a Task Control Block (TCB) in preparation + * for starting a new thread. + * + * task_schedsetup() is called from task_init(), task_start(), and + * pthread_create(); + * + * Input Parameters: + * tcb - Address of the new task's TCB + * priority - Priority of the new task + * entry - Entry point of a new task + * main - Application start point of the new task + * type - Type of the new thread: task, pthread, or kernel thread + * + * Return Value: + * OK on success; ERROR on failure. + * + * This function can only failure is it is unable to assign a new, unique + * task ID to the TCB (errno is not set). + * + ****************************************************************************/ + +int task_schedsetup(FAR _TCB *tcb, int priority, start_t start, main_t main) +{ + int ret; + + /* Assign a unique task ID to the task. */ + + ret = task_assignpid(tcb); + if (ret == OK) + { + /* Save task priority and entry point in the TCB */ + + tcb->init_priority = (uint8_t)priority; + tcb->sched_priority = (uint8_t)priority; +#ifdef CONFIG_PRIORITY_INHERITANCE + tcb->base_priority = (uint8_t)priority; +#endif + tcb->start = start; + tcb->entry.main = main; + + /* exec() and pthread_create() inherit the signal mask of the + * parent thread. I suppose that task_create() should as well. + */ + +#ifndef CONFIG_DISABLE_SIGNALS + (void)sigprocmask(SIG_SETMASK, NULL, &tcb->sigprocmask); +#endif + + /* Initialize the task state. It does not get a valid state + * until it is activated. + */ + + tcb->task_state = TSTATE_TASK_INVALID; + + /* Clone the parent tasks D-Space (if it was running PIC). This + * must be done before calling up_initial_state() so that the + * state setup will take the PIC address base into account. + */ + + task_dupdspace(tcb); + + /* Initialize the processor-specific portion of the TCB */ + + up_initial_state(tcb); + + /* Add the task to the inactive task list */ + + sched_lock(); + dq_addfirst((FAR dq_entry_t*)tcb, (dq_queue_t*)&g_inactivetasks); + tcb->task_state = TSTATE_TASK_INACTIVE; + sched_unlock(); + } + + return ret; +} + +/**************************************************************************** + * Name: task_argsetup + * + * Description: + * This functions sets up parameters in the Task Control + * Block (TCB) in preparation for starting a new thread. + * + * task_argsetup() is called only from task_init() and + * task_start() to create a new task. Argumens are + * cloned via strdup. + * + * Input Parameters: + * tcb - Address of the new task's TCB + * name - Name of the new task (not used) + * argv - A pointer to an array of input parameters. + * Up to CONFIG_MAX_TASK_ARG parameters may be + * provided. If fewer than CONFIG_MAX_TASK_ARG + * parameters are passed, the list should be + * terminated with a NULL argv[] value. + * If no parameters are required, argv may be NULL. + * + * Return Value: + * OK + * + ****************************************************************************/ + +int task_argsetup(FAR _TCB *tcb, const char *name, const char *argv[]) +{ + int i; + +#if CONFIG_TASK_NAME_SIZE > 0 + /* Give a name to the unnamed tasks */ + + if (!name) + { + name = (char *)g_noname; + } + + /* Copy the name into the TCB */ + + strncpy(tcb->name, name, CONFIG_TASK_NAME_SIZE); + + /* Save the name as the first argument */ + + tcb->argv[0] = tcb->name; +#else + /* Save the name as the first argument */ + + tcb->argv[0] = (char *)g_noname; +#endif /* CONFIG_TASK_NAME_SIZE */ + + /* For tasks, the life of the argument must be as long as + * the life of the task and the arguments must be strings. + * So for tasks, we have to to dup the strings. + * + * The first NULL argument terminates the list of + * arguments. The argv pointer may be NULL if no + * parameters are passed. + */ + + i = 1; + if (argv) + { + for (; i < CONFIG_MAX_TASK_ARGS+1 && argv[i-1]; i++) + { + tcb->argv[i] = strdup(argv[i-1]); + } + } + + /* Nullify any unused argument storage */ + + for (; i < CONFIG_MAX_TASK_ARGS+1; i++) + { + tcb->argv[i] = NULL; + } + + return OK; +} diff --git a/nuttx/sched/task_start.c b/nuttx/sched/task_start.c new file mode 100644 index 000000000..a9cc38dfc --- /dev/null +++ b/nuttx/sched/task_start.c @@ -0,0 +1,114 @@ +/**************************************************************************** + * sched/task_start.c + * + * Copyright (C) 2007-2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include + +#include "os_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: task_start + * + * Description: + * This function is the low level entry point into the main thread of + * execution of a task. It receives initial control when the task is + * started and calls main entry point of the newly started task. + * + * Inputs: + * None + * + * Return: + * None + * + ****************************************************************************/ + +void task_start(void) +{ + FAR _TCB *tcb = (FAR _TCB*)g_readytorun.head; + int argc; + + /* Count how many non-null arguments we are passing */ + + for (argc = 1; argc <= CONFIG_MAX_TASK_ARGS; argc++) + { + /* The first non-null argument terminates the list */ + + if (!tcb->argv[argc]) + { + break; + } + } + + /* Call the 'main' entry point passing argc and argv. If/when + * the task returns. + */ + + exit(tcb->entry.main(argc, tcb->argv)); +} diff --git a/nuttx/sched/timer_create.c b/nuttx/sched/timer_create.c new file mode 100644 index 000000000..edfb01080 --- /dev/null +++ b/nuttx/sched/timer_create.c @@ -0,0 +1,237 @@ +/******************************************************************************** + * sched/timer_create.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include +#include + +#include + +#include "timer_internal.h" + +#ifndef CONFIG_DISABLE_POSIX_TIMERS + +/******************************************************************************** + * Definitions + ********************************************************************************/ + +/******************************************************************************** + * Private Data + ********************************************************************************/ + +/******************************************************************************** + * Public Data + ********************************************************************************/ + +/******************************************************************************** + * Private Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: timer_allocate + * + * Description: + * Allocate one POSIX timer and place it into the allocated timer list. + * + ********************************************************************************/ + +static struct posix_timer_s *timer_allocate(void) +{ + struct posix_timer_s *ret; + irqstate_t flags; + uint8_t pt_flags; + + /* Try to get a preallocated timer from the free list */ + +#if CONFIG_PREALLOC_TIMERS > 0 + flags = irqsave(); + ret = (struct posix_timer_s*)sq_remfirst((sq_queue_t*)&g_freetimers); + irqrestore(flags); + + /* Did we get one? */ + + if (ret) + { + pt_flags = PT_FLAGS_PREALLOCATED; + } + else +#endif + { + /* Allocate a new timer from the heap */ + + ret = (struct posix_timer_s*)kmalloc(sizeof(struct posix_timer_s)); + pt_flags = 0; + } + + /* If we have a timer, then put it into the allocated timer list */ + + if (ret) + { + /* Initialize the timer structure */ + + memset(ret, 0, sizeof(struct posix_timer_s)); + ret->pt_flags = pt_flags; + + /* And add it to the end of the list of allocated timers */ + + flags = irqsave(); + sq_addlast((sq_entry_t*)ret, (sq_queue_t*)&g_alloctimers); + irqrestore(flags); + } + + return ret; +} + +/******************************************************************************** + * Public Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: timer_create + * + * Description: + * The timer_create() function creates per-thread timer using the specified + * clock, clock_id, as the timing base. The timer_create() function returns, in + * the location referenced by timerid, a timer ID of type timer_t used to identify + * the timer in timer requests. This timer ID is unique until the timer is + * deleted. The particular clock, clock_id, is defined in . The timer + * whose ID is returned will be in a disarmed state upon return from + * timer_create(). + * + * The evp argument, if non-NULL, points to a sigevent structure. This structure + * is allocated by the called and defines the asynchronous notification to occur. + * If the evp argument is NULL, the effect is as if the evp argument pointed to + * a sigevent structure with the sigev_notify member having the value SIGEV_SIGNAL, + * the sigev_signo having a default signal number, and the sigev_value member + * having the value of the timer ID. + * + * Each implementation defines a set of clocks that can be used as timing bases + * for per-thread timers. All implementations shall support a clock_id of + * CLOCK_REALTIME. + * + * Parameters: + * clockid - Specifies the clock to use as the timing base. + * evp - Refers to a user allocated sigevent structure that defines the + * asynchronous notification. evp may be NULL (see above). + * timerid - The pre-thread timer created by the call to timer_create(). + * + * Return Value: + * If the call succeeds, timer_create() will return 0 (OK) and update the + * location referenced by timerid to a timer_t, which can be passed to the + * other per-thread timer calls. If an error occurs, the function will return + * a value of -1 (ERROR) and set errno to indicate the error. + * + * EAGAIN - The system lacks sufficient signal queuing resources to honor the + * request. + * EAGAIN - The calling process has already created all of the timers it is + * allowed by this implementation. + * EINVAL - The specified clock ID is not defined. + * ENOTSUP - The implementation does not support the creation of a timer attached + * to the CPU-time clock that is specified by clock_id and associated with a + * thread different thread invoking timer_create(). + * + * Assumptions: + * + ********************************************************************************/ + +int timer_create(clockid_t clockid, FAR struct sigevent *evp, FAR timer_t *timerid) +{ + struct posix_timer_s *ret; + WDOG_ID wdog; + + /* Sanity checks. Also, we support only CLOCK_REALTIME */ + + if (!timerid || clockid != CLOCK_REALTIME) + { + errno = EINVAL; + return ERROR; + } + + /* Allocate a watchdog to provide the underling CLOCK_REALTIME timer */ + + wdog = wd_create(); + if (!wdog) + { + errno = EAGAIN; + return ERROR; + } + + /* Allocate a timer instance to contain the watchdog */ + + ret = timer_allocate(); + if (!ret) + { + errno = EAGAIN; + return ERROR; + } + + /* Initialize the timer instance */ + + ret->pt_crefs = 1; + ret->pt_owner = getpid(); + ret->pt_delay = 0; + ret->pt_wdog = wdog; + + if (evp) + { + ret->pt_signo = evp->sigev_signo; +#ifdef CONFIG_CAN_PASS_STRUCTS + ret->pt_value = evp->sigev_value; +#else + ret->pt_value.sival_ptr = evp->sigev_value.sival_ptr; +#endif + } + else + { + ret->pt_signo = SIGALRM; + ret->pt_value.sival_ptr = ret; + } + + /* Return the timer */ + + *timerid = ret; + return OK; +} + +#endif /* CONFIG_DISABLE_POSIX_TIMERS */ diff --git a/nuttx/sched/timer_delete.c b/nuttx/sched/timer_delete.c new file mode 100644 index 000000000..c497c414e --- /dev/null +++ b/nuttx/sched/timer_delete.c @@ -0,0 +1,106 @@ +/******************************************************************************** + * timer_delete.c + * + * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include + +#include "timer_internal.h" + +#ifndef CONFIG_DISABLE_POSIX_TIMERS + +/******************************************************************************** + * Definitions + ********************************************************************************/ + +/******************************************************************************** + * Private Data + ********************************************************************************/ + +/******************************************************************************** + * Public Data + ********************************************************************************/ + +/******************************************************************************** + * Private Functions + ********************************************************************************/ + +/******************************************************************************** + * Public Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: timer_delete + * + * Description: + * The timer_delete() function deletes the specified timer, timerid, previously + * created by the timer_create() function. If the timer is armed when + * timer_delete() is called, the timer will be automatically disarmed before + * removal. The disposition of pending signals for the deleted timer is + * unspecified. + * + * Parameters: + * timerid - The per-thread timer, previously created by the call to + * timer_create(), to be deleted. + * + * Return Value: + * If the call succeeds, timer_create() will return 0 (OK). Otherwise, the + * function will return a value of -1 (ERROR) and set errno to indicate the + * error. + * + * EINVAL - The timer specified timerid is not valid. + * + * Assumptions: + * + ********************************************************************************/ + +int timer_delete(timer_t timerid) +{ + int ret = timer_release((FAR struct posix_timer_s *)timerid); + if (ret < 0) + { + set_errno(-ret); + return ERROR; + } + + return OK; +} + +#endif /* CONFIG_DISABLE_POSIX_TIMERS */ diff --git a/nuttx/sched/timer_getoverrun.c b/nuttx/sched/timer_getoverrun.c new file mode 100644 index 000000000..6d5a47465 --- /dev/null +++ b/nuttx/sched/timer_getoverrun.c @@ -0,0 +1,111 @@ +/******************************************************************************** + * timer_getoverrun.c + * + * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include + +#include "timer_internal.h" + +#ifndef CONFIG_DISABLE_POSIX_TIMERS + +/******************************************************************************** + * Definitions + ********************************************************************************/ + +/******************************************************************************** + * Private Data + ********************************************************************************/ + +/******************************************************************************** + * Public Data + ********************************************************************************/ + +/******************************************************************************** + * Private Functions + ********************************************************************************/ + +/******************************************************************************** + * Public Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: timer_getoverrun + * + * Description: + * Only a single signal will be queued to the process for a given timer at any + * point in time. When a timer for which a signal is still pending expires, no + * signal will be queued, and a timer overrun will occur. When a timer + * expiration signal is delivered to or accepted by a process, if the + * implementation supports the Realtime Signals Extension, the + * timer_getoverrun() function will return the timer expiration overrun count for + * the specified timer. The overrun count returned contains the number of extra + * timer expirations that occurred between the time the signal was generated + * (queued) and when it was delivered or accepted, up to but not including an + * implementation-defined maximum of DELAYTIMER_MAX. If the number of such + * extra expirations is greater than or equal to DELAYTIMER_MAX, then the + * overrun count will be set to DELAYTIMER_MAX. The value returned by + * timer_getoverrun() will apply to the most recent expiration signal delivery + * or acceptance for the timer. If no expiration signal has been delivered + * for the timer, or if the Realtime Signals Extension is not supported, the + * return value of timer_getoverrun() is unspecified. + * + * Parameters: + * timerid - The pre-thread timer, previously created by the call to + * timer_create(), whose overrun count will be returned.. + * + * Return Value: + * If the timer_getoverrun() function succeeds, it will return the timer + * expiration overrun count as explained above. timer_getoverrun() will fail if: + * + * EINVAL - The timerid argument does not correspond to an ID returned by + * timer_create() but not yet deleted by timer_delete(). + * + * Assumptions: + * + ********************************************************************************/ + +int timer_getoverrun(timer_t timerid) +{ + errno = ENOSYS; + return ERROR; +} + +#endif /* CONFIG_DISABLE_POSIX_TIMERS */ diff --git a/nuttx/sched/timer_gettime.c b/nuttx/sched/timer_gettime.c new file mode 100644 index 000000000..7598dbec5 --- /dev/null +++ b/nuttx/sched/timer_gettime.c @@ -0,0 +1,123 @@ +/******************************************************************************** + * timer_gettime.c + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include + +#include "clock_internal.h" +#include "timer_internal.h" + +#ifndef CONFIG_DISABLE_POSIX_TIMERS + +/******************************************************************************** + * Definitions + ********************************************************************************/ + +/******************************************************************************** + * Private Data + ********************************************************************************/ + +/******************************************************************************** + * Public Data + ********************************************************************************/ + +/******************************************************************************** + * Private Functions + ********************************************************************************/ + +/******************************************************************************** + * Public Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: timer_gettime + * + * Description: + * The timer_gettime() function will store the amount of time until the + * specified timer, timerid, expires and the reload value of the timer into the + * space pointed to by the value argument. The it_value member of this structure + * will contain the amount of time before the timer expires, or zero if the timer + * is disarmed. This value is returned as the interval until timer expiration, + * even if the timer was armed with absolute time. The it_interval member of + * value will contain the reload value last set by timer_settime(). + * + * Parameters: + * timerid - The pre-thread timer, previously created by the call to + * timer_create(), whose remaining time count will be returned.. + * + * Return Value: + * If the timer_gettime() succeeds, a value of 0 (OK) will be returned. + * If an error occurs, the value -1 (ERROR) will be returned, and errno set to + * indicate the error. + * + * EINVAL - The timerid argument does not correspond to an ID returned by + * timer_create() but not yet deleted by timer_delete(). + * + * Assumptions/Limitations: + * Due to the asynchronous operation of this function, the time reported + * by this function could be significantly more than that actual time + * remaining on the timer at any time. + * + ********************************************************************************/ + +int timer_gettime(timer_t timerid, FAR struct itimerspec *value) +{ + FAR struct posix_timer_s *timer = (FAR struct posix_timer_s *)timerid; + int ticks; + + if (!timer || !value) + { + set_errno(EINVAL); + return ERROR; + } + + /* Get the number of ticks before the underlying watchdog expires */ + + ticks = wd_gettime(timer->pt_wdog); + + /* Convert that to a struct timespec and return it */ + + (void)clock_ticks2time(ticks, &value->it_value); + (void)clock_ticks2time(timer->pt_last, &value->it_interval); + return OK; +} + +#endif /* CONFIG_DISABLE_POSIX_TIMERS */ diff --git a/nuttx/sched/timer_initialize.c b/nuttx/sched/timer_initialize.c new file mode 100644 index 000000000..05980bb1a --- /dev/null +++ b/nuttx/sched/timer_initialize.c @@ -0,0 +1,168 @@ +/******************************************************************************** + * timer_initialize.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include + +#include +#include +#include +#include + +#include "timer_internal.h" + +#ifndef CONFIG_DISABLE_POSIX_TIMERS + +/******************************************************************************** + * Definitions + ********************************************************************************/ + +/******************************************************************************** + * Private Data + ********************************************************************************/ + +/* These are the preallocated times */ + +#if CONFIG_PREALLOC_TIMERS > 0 +static struct posix_timer_s g_prealloctimers[CONFIG_PREALLOC_TIMERS]; +#endif + +/******************************************************************************** + * Public Data + ********************************************************************************/ + +/* This is a list of free, preallocated timer structures */ + +#if CONFIG_PREALLOC_TIMERS > 0 +volatile sq_queue_t g_freetimers; +#endif + +/* This is a list of instantiated timer structures -- active and inactive. The + * timers are place on this list by timer_create() and removed from the list by + * timer_delete() or when the owning thread exits. + */ + +volatile sq_queue_t g_alloctimers; + +/******************************************************************************** + * Private Functions + ********************************************************************************/ + +/******************************************************************************** + * Public Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: timer_initialize + * + * Description: + * Boot up configuration of the POSIX timer facility. + * + * Parameters: + * None + * + * Return Value: + * None + * + * Assumptions: + * + ********************************************************************************/ + +void weak_function timer_initialize(void) +{ +#if CONFIG_PREALLOC_TIMERS > 0 + int i; + + /* Place all of the pre-allocated timers into the free timer list */ + + sq_init((sq_queue_t*)&g_freetimers); + + for (i = 0; i < CONFIG_PREALLOC_TIMERS; i++) + { + g_prealloctimers[i].pt_flags = PT_FLAGS_PREALLOCATED; + sq_addlast((FAR sq_entry_t*)&g_prealloctimers[i], (FAR sq_queue_t*)&g_freetimers); + } +#endif + + /* Initialize the list of allocated timers */ + + sq_init((sq_queue_t*)&g_alloctimers); +} + +/******************************************************************************** + * Name: timer_deleteall + * + * Description: + * This function is called whenever a thread exits. Any timers owned by that + * thread are deleted as though called by timer_delete(). + * + * It is provided in this file so that it can be weakly defined but also, + * like timer_intitialize(), be brought into the link whenever the timer + * resources are referenced. + * + * Parameters: + * pid - the task ID of the thread that exitted + * + * Return Value: + * None + * + * Assumptions: + * + ********************************************************************************/ + +void weak_function timer_deleteall(pid_t pid) +{ + FAR struct posix_timer_s *timer; + FAR struct posix_timer_s *next; + irqstate_t flags; + + flags = irqsave(); + for (timer = (FAR struct posix_timer_s*)g_alloctimers.head; timer; timer = next) + { + next = timer->flink; + if (timer->pt_owner == pid) + { + timer_delete((timer_t)timer); + } + } + + irqrestore(flags); +} + +#endif /* CONFIG_DISABLE_POSIX_TIMERS */ diff --git a/nuttx/sched/timer_internal.h b/nuttx/sched/timer_internal.h new file mode 100644 index 000000000..71dfb59a3 --- /dev/null +++ b/nuttx/sched/timer_internal.h @@ -0,0 +1,102 @@ +/******************************************************************************** + * timer_internal.h + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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. + * + ********************************************************************************/ + +#ifndef __SCHED_TIMER_INTERNAL_H +#define __SCHED_TIMER_INTERNAL_H + +/******************************************************************************** + * Included Files + ********************************************************************************/ + +#include + +#include +#include +#include + +#include + +/******************************************************************************** + * Definitions + ********************************************************************************/ + +#define PT_FLAGS_PREALLOCATED 0x01 /* Timer comes from a pool of preallocated timers */ + +/******************************************************************************** + * Public Types + ********************************************************************************/ + +/* This structure represents one POSIX timer */ + +struct posix_timer_s +{ + FAR struct posix_timer_s *flink; + + uint8_t pt_flags; /* See PT_FLAGS_* definitions */ + uint8_t pt_crefs; /* Reference count */ + uint8_t pt_signo; /* Notification signal */ + pid_t pt_owner; /* Creator of timer */ + int pt_delay; /* If non-zero, used to reset repetitive timers */ + int pt_last; /* Last value used to set watchdog */ + WDOG_ID pt_wdog; /* The watchdog that provides the timing */ + union sigval pt_value; /* Data passed with notification */ +}; + +/******************************************************************************** + * Public Data + ********************************************************************************/ + +/* This is a list of free, preallocated timer structures */ + +#if CONFIG_PREALLOC_TIMERS > 0 +extern volatile sq_queue_t g_freetimers; +#endif + +/* This is a list of instantiated timer structures -- active and inactive. The + * timers are place on this list by timer_create() and removed from the list by + * timer_delete() or when the owning thread exits. + */ + +extern volatile sq_queue_t g_alloctimers; + +/******************************************************************************** + * Public Function Prototypes + ********************************************************************************/ + +void weak_function timer_initialize(void); +void weak_function timer_deleteall(pid_t pid); +int timer_release(FAR struct posix_timer_s *timer); + +#endif /* __SCHED_TIMER_INTERNAL_H */ diff --git a/nuttx/sched/timer_release.c b/nuttx/sched/timer_release.c new file mode 100644 index 000000000..ed83b5f53 --- /dev/null +++ b/nuttx/sched/timer_release.c @@ -0,0 +1,159 @@ +/******************************************************************************** + * timer_release.c + * + * Copyright (C) 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include + +#include + +#include "timer_internal.h" + +#ifndef CONFIG_DISABLE_POSIX_TIMERS + +/******************************************************************************** + * Definitions + ********************************************************************************/ + +/******************************************************************************** + * Private Data + ********************************************************************************/ + +/******************************************************************************** + * Public Data + ********************************************************************************/ + +/******************************************************************************** + * Private Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: timer_free + * + * Description: + * Remove the timer from the allocated timer list and free it or return it to + * the free list (depending on whether or not the timer is one of the + * preallocated timers) + * + ********************************************************************************/ + +static inline void timer_free(struct posix_timer_s *timer) +{ + irqstate_t flags; + + /* Remove the timer from the allocated list */ + + flags = irqsave(); + sq_rem((FAR sq_entry_t*)timer, (sq_queue_t*)&g_alloctimers); + + /* Return it to the free list if it is one of the preallocated timers */ + +#if CONFIG_PREALLOC_TIMERS > 0 + if ((timer->pt_flags & PT_FLAGS_PREALLOCATED) != 0) + { + sq_addlast((FAR sq_entry_t*)timer, (FAR sq_queue_t*)&g_freetimers); + irqrestore(flags); + } + else +#endif + { + /* Otherwise, return it to the heap */ + + irqrestore(flags); + sched_free(timer); + } +} + +/******************************************************************************** + * Public Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: timer_release + * + * Description: + * timer_release implements the heart of timer_delete. It is private to the + * the OS internals and differs only in that return value of 1 means that the + * timer was not actually deleted. + * + * Parameters: + * timer - The per-thread timer, previously created by the call to + * timer_create(), to be deleted. + * + * Return Value: + * If the call succeeds, timer_release() will return 0 (OK) or 1 (meaning that + * the timer is still valid). Otherwise, the function will return a negated errno: + * + * -EINVAL - The timer specified timerid is not valid. + * + ********************************************************************************/ + +int timer_release(FAR struct posix_timer_s *timer) +{ + /* Some sanity checks */ + + if (!timer) + { + return -EINVAL; + } + + /* Release one reference to timer. Don't delete the timer until the count + * would decrement to zero. + */ + + if (timer->pt_crefs > 1) + { + timer->pt_crefs--; + return 1; + } + + /* Free the underlying watchdog instance (the timer will be canceled by the + * watchdog logic before it is actually deleted) + */ + + (void)wd_delete(timer->pt_wdog); + + /* Release the timer structure */ + + timer_free(timer); + return OK; +} + +#endif /* CONFIG_DISABLE_POSIX_TIMERS */ diff --git a/nuttx/sched/timer_settime.c b/nuttx/sched/timer_settime.c new file mode 100644 index 000000000..1814ba898 --- /dev/null +++ b/nuttx/sched/timer_settime.c @@ -0,0 +1,397 @@ +/******************************************************************************** + * sched/timer_settime.c + * + * Copyright (C) 2007-2010 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include + +#include "os_internal.h" +#include "clock_internal.h" +#include "sig_internal.h" +#include "timer_internal.h" + +#ifndef CONFIG_DISABLE_POSIX_TIMERS + +/******************************************************************************** + * Definitions + ********************************************************************************/ + +/******************************************************************************** + * Private Data + ********************************************************************************/ + +/******************************************************************************** + * Public Data + ********************************************************************************/ + +/******************************************************************************** + * Private Function Prototypes + ********************************************************************************/ + +static void inline timer_sigqueue(FAR struct posix_timer_s *timer); +static void inline timer_restart(FAR struct posix_timer_s *timer, uint32_t itimer); +static void timer_timeout(int argc, uint32_t itimer); + +/******************************************************************************** + * Private Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: timer_sigqueue + * + * Description: + * This function basically reimplements sigqueue() so that the si_code can + * be correctly set to SI_TIMER + * + * Parameters: + * timer - A reference to the POSIX timer that just timed out + * + * Return Value: + * None + * + * Assumptions: + * This function executes in the context of the watchod timer interrupt. + * + ********************************************************************************/ + +static void inline timer_sigqueue(FAR struct posix_timer_s *timer) +{ + FAR _TCB *tcb; + + /* Get the TCB of the receiving task */ + + tcb = sched_gettcb(timer->pt_owner); + if (tcb) + { + siginfo_t info; + + /* Create the siginfo structure */ + + info.si_signo = timer->pt_signo; + info.si_code = SI_TIMER; +#ifdef CONFIG_CAN_PASS_STRUCTS + info.si_value = timer->pt_value; +#else + info.si_value.sival_ptr = timer->pt_value.sival_ptr; +#endif + + /* Send the signal */ + + (void)sig_received(tcb, &info); + } +} + +/******************************************************************************** + * Name: timer_restart + * + * Description: + * If a periodic timer has been selected, then restart the watchdog. + * + * Parameters: + * timer - A reference to the POSIX timer that just timed out + * + * Return Value: + * None + * + * Assumptions: + * This function executes in the context of the watchod timer interrupt. + * + ********************************************************************************/ + +static void inline timer_restart(FAR struct posix_timer_s *timer, uint32_t itimer) +{ + /* If this is a repetitive timer, then restart the watchdog */ + + if (timer->pt_delay) + { + timer->pt_last = timer->pt_delay; + (void)wd_start(timer->pt_wdog, timer->pt_delay, (wdentry_t)timer_timeout, + 1, itimer); + } +} + +/******************************************************************************** + * Name: timer_timeout + * + * Description: + * This function is called if the timeout elapses before the condition is + * signaled. + * + * Parameters: + * argc - the number of arguments (should be 1) + * itimer - A reference to the POSIX timer that just timed out + * signo - The signal to use to wake up the task + * + * Return Value: + * None + * + * Assumptions: + * This function executes in the context of the watchod timer interrupt. + * + ********************************************************************************/ + +static void timer_timeout(int argc, uint32_t itimer) +{ +#ifndef CONFIG_CAN_PASS_STRUCTS + /* On many small machines, pointers are encoded and cannot be simply cast from + * uint32_t to _TCB*. The following union works around this (see wdogparm_t). + */ + + union + { + FAR struct posix_timer_s *timer; + uint32_t itimer; + } u; + + u.itimer = itimer; + + /* Send the specified signal to the specified task. Increment the reference + * count on the timer first so that will not be deleted until after the + * signal handler returns. + */ + + u.timer->pt_crefs++; + timer_sigqueue(u.timer); + + /* Release the reference. timer_release will return nonzero if the timer + * was not deleted. + */ + + if (timer_release(u.timer)) + { + /* If this is a repetitive timer, the restart the watchdog */ + + timer_restart(u.timer, itimer); + } +#else + /* (casting to uintptr_t first eliminates complaints on some architectures + * where the sizeof uint32_t is different from the size of a pointer). + */ + + FAR struct posix_timer_s *timer = (FAR struct posix_timer_s *)((uintptr_t)itimer); + + /* Send the specified signal to the specified task. Increment the reference + * count on the timer first so that will not be deleted until after the + * signal handler returns. + */ + + timer->pt_crefs++; + timer_sigqueue(timer); + + /* Release the reference. timer_release will return nonzero if the timer + * was not deleted. + */ + + if (timer_release(timer)) + { + /* If this is a repetitive timer, the restart the watchdog */ + + timer_restart(timer, itimer); + } +#endif +} + +/******************************************************************************** + * Public Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: timer_settime + * + * Description: + * The timer_settime() function sets the time until the next expiration of the + * timer specified by timerid from the it_value member of the value argument + * and arm the timer if the it_value member of value is non-zero. If the + * specified timer was already armed when timer_settime() is called, this call + * will reset the time until next expiration to the value specified. If the + * it_value member of value is zero, the timer will be disarmed. The effect + * of disarming or resetting a timer with pending expiration notifications is + * unspecified. + * + * If the flag TIMER_ABSTIME is not set in the argument flags, timer_settime() + * will behave as if the time until next expiration is set to be equal to the + * interval specified by the it_value member of value. That is, the timer will + * expire in it_value nanoseconds from when the call is made. If the flag + * TIMER_ABSTIME is set in the argument flags, timer_settime() will behave as + * if the time until next expiration is set to be equal to the difference between + * the absolute time specified by the it_value member of value and the current + * value of the clock associated with timerid. That is, the timer will expire + * when the clock reaches the value specified by the it_value member of value. + * If the specified time has already passed, the function will succeed and the + * expiration notification will be made. + * + * The reload value of the timer will be set to the value specified by the + * it_interval member of value. When a timer is armed with a non-zero + * it_interval, a periodic (or repetitive) timer is specified. + * + * Time values that are between two consecutive non-negative integer multiples + * of the resolution of the specified timer will be rounded up to the larger + * multiple of the resolution. Quantization error will not cause the timer to + * expire earlier than the rounded time value. + * + * If the argument ovalue is not NULL, the timer_settime() function will store, + * in the location referenced by ovalue, a value representing the previous + * amount of time before the timer would have expired, or zero if the timer was + * disarmed, together with the previous timer reload value. Timers will not + * expire before their scheduled time. + * + * Parameters: + * timerid - The pre-thread timer, previously created by the call to + * timer_create(), to be be set. + * flags - Specifie characteristics of the timer (see above) + * value - Specifies the timer value to set + * ovalue - A location in which to return the time remaining from the previous + * timer setting. (ignored) + * + * Return Value: + * If the timer_settime() succeeds, a value of 0 (OK) will be returned. + * If an error occurs, the value -1 (ERROR) will be returned, and errno set to + * indicate the error. + * + * EINVAL - The timerid argument does not correspond to an ID returned by + * timer_create() but not yet deleted by timer_delete(). + * EINVAL - A value structure specified a nanosecond value less than zero or + * greater than or equal to 1000 million, and the it_value member of that + * structure did not specify zero seconds and nanoseconds. + * + * Assumptions: + * + ********************************************************************************/ + +int timer_settime(timer_t timerid, int flags, FAR const struct itimerspec *value, + FAR struct itimerspec *ovalue) +{ + FAR struct posix_timer_s *timer = (FAR struct posix_timer_s *)timerid; + irqstate_t state; + int delay; + int ret = OK; + + /* Some sanity checks */ + + if (!timer || !value) + { + errno = EINVAL; + return ERROR; + } + + /* Disarm the timer (in case the timer was already armed when timer_settime() + * is called). + */ + + (void)wd_cancel(timer->pt_wdog); + + /* If the it_value member of value is zero, the timer will not be re-armed */ + + if (value->it_value.tv_sec <= 0 && value->it_value.tv_nsec <= 0) + { + return OK; + } + + /* Setup up any repititive timer */ + + if (value->it_interval.tv_sec > 0 || value->it_interval.tv_nsec > 0) + { + (void)clock_time2ticks(&value->it_interval, &timer->pt_delay); + } + else + { + timer->pt_delay = 0; + } + + /* We need to disable timer interrupts through the following section so + * that the system timer is stable. + */ + + state = irqsave(); + + /* Check if abstime is selected */ + + if ((flags & TIMER_ABSTIME) != 0) + { +#ifdef CONFIG_DISABLE_CLOCK + /* Absolute timing depends upon having access to clock functionality */ + + errno = ENOSYS; + return ERROR; +#else + /* Calculate a delay corresponding to the absolute time in 'value'. + * NOTE: We have internal knowledge the clock_abstime2ticks only + * returns an error if clockid != CLOCK_REALTIME. + */ + + (void)clock_abstime2ticks(CLOCK_REALTIME, &value->it_value, &delay); +#endif + } + else + { + /* Calculate a delay assuming that 'value' holds the relative time + * to wait. We have internal knowledge that clock_time2ticks always + * returns success. + */ + + (void)clock_time2ticks(&value->it_value, &delay); + } + + /* If the time is in the past or now, then set up the next interval + * instead (assuming a repititive timer). + */ + + if (delay <= 0) + { + delay = timer->pt_delay; + } + + /* Then start the watchdog */ + + + if (delay > 0) + { + timer->pt_last = delay; + ret = wd_start(timer->pt_wdog, delay, (wdentry_t)timer_timeout, + 1, (uint32_t)((uintptr_t)timer)); + } + + irqrestore(state); + return ret; +} + +#endif /* CONFIG_DISABLE_POSIX_TIMERS */ diff --git a/nuttx/sched/usleep.c b/nuttx/sched/usleep.c new file mode 100644 index 000000000..21996d788 --- /dev/null +++ b/nuttx/sched/usleep.c @@ -0,0 +1,168 @@ +/**************************************************************************** + * sched/usleep.c + * + * Copyright (C) 2007, 2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include +#include +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: usleep + * + * Description: + * The usleep() function will cause the calling thread to be suspended + * from execution until either the number of real-time microseconds + * specified by the argument 'usec' has elapsed or a signal is delivered + * to the calling thread. The suspension time may be longer than requested + * due to the scheduling of other activity by the system. + * + * The 'usec' argument must be less than 1,000,000. If the value of + * 'usec' is 0, then the call has no effect. + * + * If a SIGALRM signal is generated for the calling process during + * execution of usleep() and if the SIGALRM signal is being ignored or + * blocked from delivery, it is unspecified whether usleep() returns + * when the SIGALRM signal is scheduled. If the signal is being blocked, it + * is also unspecified whether it remains pending after usleep() returns or + * it is discarded. + * + * If a SIGALRM signal is generated for the calling process during + * execution of usleep(), except as a result of a prior call to alarm(), + * and if the SIGALRM signal is not being ignored or blocked from delivery, + * it is unspecified whether that signal has any effect other than causing + * usleep() to return. + * + * If a signal-catching function interrupts usleep() and examines or changes + * either the time a SIGALRM is scheduled to be generated, the action + * associated with the SIGALRM signal, or whether the SIGALRM signal is + * blocked from delivery, the results are unspecified. + * + * If a signal-catching function interrupts usleep() and calls siglongjmp() + * or longjmp() to restore an environment saved prior to the usleep() call, + * the action associated with the SIGALRM signal and the time at which a + * SIGALRM signal is scheduled to be generated are unspecified. It is also + * unspecified whether the SIGALRM signal is blocked, unless the process' + * signal mask is restored as part of the environment. + * + * Implementations may place limitations on the granularity of timer values. + * For each interval timer, if the requested timer value requires a finer + * granularity than the implementation supports, the actual timer value will + * be rounded up to the next supported value. + * + * Interactions between usleep() and any of the following are unspecified: + * + * nanosleep(), setitimer(), timer_create(), timer_delete(), timer_getoverrun(), + * timer_gettime(), timer_settime(), ualarm(), sleep() + + * Parameters: + * usec - the number of microseconds to wait. + * + * Returned Value: + * On successful completion, usleep() returns 0. Otherwise, it returns -1 + * and sets errno to indicate the error. + * + * Assumptions: + * + ****************************************************************************/ + +int usleep(useconds_t usec) +{ + sigset_t set; + struct timespec ts; + struct siginfo value; + int errval; + int ret = 0; + + if (usec) + { + /* Set up for the sleep. Using the empty set means that we are not + * waiting for any particualar signal. However, any unmasked signal + * can still awaken sigtimedwait(). + */ + + (void)sigemptyset(&set); + ts.tv_sec = usec / 1000000; + ts.tv_nsec = (usec % 1000000) * 1000; + + /* usleep is a simple application of sigtimedwait. */ + + ret = sigtimedwait(&set, &value, &ts); + + /* 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 = errno; + DEBUGASSERT(ret < 0 && (errval == EAGAIN || errval == EINTR)); + if (errval == EAGAIN) + { + /* The timeout "error" is the normal, successful result */ + + ret = 0; + } + } + + return ret; +} diff --git a/nuttx/sched/wd_cancel.c b/nuttx/sched/wd_cancel.c new file mode 100644 index 000000000..0bd59cf89 --- /dev/null +++ b/nuttx/sched/wd_cancel.c @@ -0,0 +1,165 @@ +/**************************************************************************** + * sched/wd_cancel.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include + +#include "os_internal.h" +#include "wd_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: wd_cancel + * + * Description: + * This function cancels a currently running watchdog timer. Watchdog + * timers may be canceled from the interrupt level. + * + * Parameters: + * wdid - ID of the watchdog to cancel. + * + * Return Value: + * OK or ERROR + * + * Assumptions: + * + ****************************************************************************/ + +int wd_cancel (WDOG_ID wdid) +{ + wdog_t *curr; + wdog_t *prev; + irqstate_t saved_state; + int ret = ERROR; + + /* Prohibit timer interactions with the timer queue until the + * cancellation is complete + */ + + saved_state = irqsave(); + + /* Make sure that the watchdog is initialed (non-NULL) and is still active */ + + if (wdid && wdid->active) + { + /* Search the g_wdactivelist for the target FCB. We can't use sq_rem + * to do this because there are additional operations that need to be + * done. + */ + + prev = NULL; + curr = (wdog_t*)g_wdactivelist.head; + + while((curr) && (curr != wdid)) + { + prev = curr; + curr = curr->next; + } + + /* Check if the watchdog was found in the list. If not, then an OS + * error has occurred because the watchdog is marked active! + */ + + if (!curr) + { + PANIC(OSERR_WDOGNOTFOUND); + } + else + { + /* If there is a watchdog in the timer queue after the one that + * is being canceled, then it inherits the remaining ticks. + */ + + if (curr->next) + { + curr->next->lag += curr->lag; + } + + /* Now, remove the watchdog from the timer queue */ + + if (prev) + { + (void)sq_remafter((FAR sq_entry_t*)prev, &g_wdactivelist); + } + else + { + (void)sq_remfirst(&g_wdactivelist); + } + wdid->next = NULL; + + /* Return success */ + + ret = OK; + } + + /* Mark the watchdog inactive */ + + wdid->active = false; + } + + irqrestore(saved_state); + return ret; +} diff --git a/nuttx/sched/wd_create.c b/nuttx/sched/wd_create.c new file mode 100644 index 000000000..d86171bf7 --- /dev/null +++ b/nuttx/sched/wd_create.c @@ -0,0 +1,109 @@ +/**************************************************************************** + * sched/wd_create.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include + +#include "wd_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: wd_create + * + * Description: + * The wd_create function will create a watchdog by allocating it from the + * list of free watchdogs. + * + * Parameters: + * None + * + * Return Value: + * Pointer to watchdog (i.e., the watchdog ID), or NULL if insufficient + * watchdogs are available. + * + * Assumptions: + * + ****************************************************************************/ + +WDOG_ID wd_create (void) +{ + FAR wdog_t *wdog; + irqstate_t saved_state; + + saved_state = irqsave(); + wdog = (FAR wdog_t*)sq_remfirst(&g_wdfreelist); + irqrestore(saved_state); + + /* Indicate that the watchdog is not actively timing */ + + if (wdog) + { + wdog->next = NULL; + wdog->active = false; + } + + return (WDOG_ID)wdog; +} diff --git a/nuttx/sched/wd_delete.c b/nuttx/sched/wd_delete.c new file mode 100644 index 000000000..16c123e13 --- /dev/null +++ b/nuttx/sched/wd_delete.c @@ -0,0 +1,127 @@ +/**************************************************************************** + * sched/wd_delete.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include + +#include + +#include "wd_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: wd_delete + * + * Description: + * The wd_delete function will deallocate a watchdog by returning it to + * the free pool of watchdogs. The watchdog will be removed from the timer + * queue if has been started. + * + * Parameters: + * wdId - The watchdog ID to delete. This is actually a pointer to a + * watchdog structure. + * + * Return Value: + * Returns OK or ERROR + * + * Assumptions: + * The caller has assured that the watchdog is no longer in use. + * + ****************************************************************************/ + +int wd_delete(WDOG_ID wdId) +{ + irqstate_t saved_state; + + /* Verify that a valid watchdog was provided */ + + if (!wdId) + { + set_errno(EINVAL); + return ERROR; + } + + /* The following steps are atomic... the watchdog must not be active when + * it is being deallocated. + */ + + saved_state = irqsave(); + + /* Check if the watchdog has been started. */ + + if (wdId->active) + { + wd_cancel(wdId); + } + + /* Put the watchdog back on the free list */ + + sq_addlast((FAR sq_entry_t*)wdId, &g_wdfreelist); + irqrestore(saved_state); + + /* Return success */ + + return OK; +} diff --git a/nuttx/sched/wd_gettime.c b/nuttx/sched/wd_gettime.c new file mode 100644 index 000000000..caa482549 --- /dev/null +++ b/nuttx/sched/wd_gettime.c @@ -0,0 +1,118 @@ +/******************************************************************************** + * sched/wd_gettime.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include + +#include "os_internal.h" +#include "wd_internal.h" + +/******************************************************************************** + * Definitions + ********************************************************************************/ + +/******************************************************************************** + * Private Types + ********************************************************************************/ + +/******************************************************************************** + * Global Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Variables + ********************************************************************************/ + +/******************************************************************************** + * Private Functions + ********************************************************************************/ + +/******************************************************************************** + * Public Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: wd_gettime + * + * Description: + * This function returns the time remaining before the specified watchdog + * expires. + * + * Parameters: + * wdog = watchdog ID + * + * Return Value: + * The time in system ticks remaining until the watchdog time expires. Zero + * means either that wdog is not valid or that the wdog has already expired. + * + * Assumptions: + * + ********************************************************************************/ + +int wd_gettime(WDOG_ID wdog) +{ + irqstate_t flags; + + /* Verify the wdog */ + + flags = irqsave(); + if (wdog && wdog->active) + { + /* Traverse the watchdog list accumulating lag times until we find the wdog + * that we are looking for + */ + + wdog_t *curr; + int delay = 0; + + for (curr = (wdog_t*)g_wdactivelist.head; curr; curr = curr->next) + { + delay += curr->lag; + if (curr == wdog) + { + irqrestore(flags); + return delay; + } + } + } + + irqrestore(flags); + return 0; +} diff --git a/nuttx/sched/wd_initialize.c b/nuttx/sched/wd_initialize.c new file mode 100644 index 000000000..db7aba502 --- /dev/null +++ b/nuttx/sched/wd_initialize.c @@ -0,0 +1,135 @@ +/************************************************************************ + * sched/wd_initialize.c + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include + +#include "os_internal.h" +#include "wd_internal.h" + +/************************************************************************ + * Definitions + ************************************************************************/ + +/************************************************************************ + * Private Type Declarations + ************************************************************************/ + +/************************************************************************ + * Global Variables + ************************************************************************/ + +/* The g_wdfreelist data structure is a singly linked list of watchdogs + * available to the system for delayed function use. + */ + +sq_queue_t g_wdfreelist; + +/* g_wdpool is a pointer to a list of pre-allocated watchdogs. The number + * of watchdogs in the pool is a configuration item. + */ + +FAR wdog_t *g_wdpool; + +/* The g_wdactivelist data structure is a singly linked list ordered by + * watchdog expiration time. When watchdog timers expire,the functions on + * this linked list are removed and the function is called. + */ + +sq_queue_t g_wdactivelist; + +/************************************************************************ + * Private Variables + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: wd_initialize + * + * Description: + * This function initalized the watchdog data structures + * + * Parameters: + * None + * + * Return Value: + * None + * + * Assumptions: + * This function must be called early in the initialization sequence + * before the timer interrupt is attached and before any watchdog + * services are used. + * + ************************************************************************/ + +void wd_initialize(void) +{ + /* Initialize the free watchdog list */ + + sq_init(&g_wdfreelist); + + /* The g_wdfreelist must be loaded at initialization time to hold the + * configured number of watchdogs. + */ + + g_wdpool = (FAR wdog_t*)kmalloc(sizeof(wdog_t) * CONFIG_PREALLOC_WDOGS); + if (g_wdpool) + { + FAR wdog_t *wdog = g_wdpool; + int i; + + for (i = 0; i < CONFIG_PREALLOC_WDOGS; i++) + { + sq_addlast((FAR sq_entry_t*)wdog++, &g_wdfreelist); + } + } + + /* The g_wdactivelist queue must be reset at initialization time. */ + + sq_init(&g_wdactivelist); +} diff --git a/nuttx/sched/wd_internal.h b/nuttx/sched/wd_internal.h new file mode 100644 index 000000000..e63a8bdae --- /dev/null +++ b/nuttx/sched/wd_internal.h @@ -0,0 +1,119 @@ +/************************************************************************ + * sched/d_internal.h + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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. + * + ************************************************************************/ + +#ifndef __SCHED_WD_INTERNAL_H +#define __SCHED_WD_INTERNAL_H + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include + +#include +#include +#include + +#include + +/************************************************************************ + * Pre-processor Definitions + ************************************************************************/ + +/************************************************************************ + * Public Type Declarations + ************************************************************************/ + +/* This is the watchdog structure. The WDOG_ID is a pointer to a + * watchdog structure. + */ + +struct wdog_s +{ + FAR struct wdog_s *next; /* Support for singly linked lists. */ + wdentry_t func; /* Function to execute when delay expires */ +#ifdef CONFIG_PIC + FAR void *picbase; /* PIC base address */ +#endif + int lag; /* Timer associated with the delay */ + bool active; /* true if the watchdog is actively timing */ + uint8_t argc; /* The number of parameters to pass */ + uint32_t parm[CONFIG_MAX_WDOGPARMS]; +}; +typedef struct wdog_s wdog_t; + +/************************************************************************ + * Public Variables + ************************************************************************/ + +/* The g_wdfreelist data structure is a singly linked list of watchdogs + * available to the system for delayed function use. + */ + +extern sq_queue_t g_wdfreelist; + +/* g_wdpool is a pointer to a list of pre-allocated watchdogs. The number + * of watchdogs in the pool is a configuration item. + */ + +extern FAR wdog_t *g_wdpool; + +/* The g_wdactivelist data structure is a singly linked list ordered by + * watchdog expiration time. When watchdog timers expire,the functions on + * this linked list are removed and the function is called. + */ + +extern sq_queue_t g_wdactivelist; + +/************************************************************************ + * Public Function Prototypes + ************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +EXTERN void weak_function wd_initialize(void); +EXTERN void weak_function wd_timer(void); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __SCHED_WD_INTERNAL_H */ diff --git a/nuttx/sched/wd_start.c b/nuttx/sched/wd_start.c new file mode 100644 index 000000000..2a69d131a --- /dev/null +++ b/nuttx/sched/wd_start.c @@ -0,0 +1,375 @@ +/**************************************************************************** + * sched/wd_start.c + * + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "os_internal.h" +#include "wd_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +typedef void (*wdentry0_t)(int argc); +#if CONFIG_MAX_WDOGPARMS > 0 +typedef void (*wdentry1_t)(int argc, uint32_t arg1); +#endif +#if CONFIG_MAX_WDOGPARMS > 1 +typedef void (*wdentry2_t)(int argc, uint32_t arg1, uint32_t arg2); +#endif +#if CONFIG_MAX_WDOGPARMS > 2 +typedef void (*wdentry3_t)(int argc, uint32_t arg1, uint32_t arg2, + uint32_t arg3); +#endif +#if CONFIG_MAX_WDOGPARMS > 3 +typedef void (*wdentry4_t)(int argc, uint32_t arg1, uint32_t arg2, + uint32_t arg3, uint32_t arg4); +#endif + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: wd_start + * + * Description: + * This function adds a watchdog to the timer queue. The specified + * watchdog function will be called from the interrupt level after the + * specified number of ticks has elapsed. Watchdog timers may be started + * from the interrupt level. + * + * Watchdog timers execute in the address enviroment that was in effect + * when wd_start() is called. + * + * Watchdog timers execute only once. + * + * To replace either the timeout delay or the function to be executed, + * call wd_start again with the same wdog; only the most recent wdStart() + * on a given watchdog ID has any effect. + * + * Parameters: + * wdog = watchdog ID + * delay = Delay count in clock ticks + * wdentry = function to call on timeout + * parm1..4 = parameters to pass to wdentry + * + * Return Value: + * OK or ERROR + * + * Assumptions: + * The watchdog routine runs in the context of the timer interrupt handler + * and is subject to all ISR restrictions. + * + ****************************************************************************/ + +int wd_start(WDOG_ID wdog, int delay, wdentry_t wdentry, int argc, ...) +{ + va_list ap; + FAR wdog_t *curr; + FAR wdog_t *prev; + FAR wdog_t *next; + int32_t now; + irqstate_t saved_state; + int i; + + /* Verify the wdog */ + + if (!wdog || argc > CONFIG_MAX_WDOGPARMS || delay < 0) + { + set_errno(EINVAL); + return ERROR; + } + + /* Check if the watchdog has been started. If so, stop it. + * NOTE: There is a race condition here... the caller may receive + * the watchdog between the time that wd_start is called and + * the critical section is established. + */ + + saved_state = irqsave(); + if (wdog->active) + { + wd_cancel(wdog); + } + + /* Save the data in the watchdog structure */ + + wdog->func = wdentry; /* Function to execute when delay expires */ + up_getpicbase(&wdog->picbase); + wdog->argc = argc; + + va_start(ap, argc); + for (i = 0; i < argc; i++) + { + wdog->parm[i] = va_arg(ap, uint32_t); + } +#ifdef CONFIG_DEBUG + for (; i < CONFIG_MAX_WDOGPARMS; i++) + { + wdog->parm[i] = 0; + } +#endif + va_end(ap); + + /* Calculate delay+1, forcing the delay into a range that we can handle */ + + if (delay <= 0) + { + delay = 1; + } + else if (++delay <= 0) + { + delay--; + } + + /* Do the easy case first -- when the watchdog timer queue is empty. */ + + if (g_wdactivelist.head == NULL) + { + sq_addlast((FAR sq_entry_t*)wdog,&g_wdactivelist); + } + + /* There are other active watchdogs in the timer queue */ + + else + { + now = 0; + prev = curr = (FAR wdog_t*)g_wdactivelist.head; + + /* Advance to positive time */ + + while ((now += curr->lag) < 0 && curr->next) + { + prev = curr; + curr = curr->next; + } + + /* Advance past shorter delays */ + + while (now <= delay && curr->next) + { + prev = curr; + curr = curr->next; + now += curr->lag; + } + + /* Check if the new wdog must be inserted before the curr. */ + + if (delay < now) + { + /* The relative delay time is smaller or equal to the current delay + * time, so decrement the current delay time by the new relative + * delay time. + */ + + delay -= (now - curr->lag); + curr->lag -= delay; + + /* Insert the new watchdog in the list */ + + if (curr == (FAR wdog_t*)g_wdactivelist.head) + { + sq_addfirst((FAR sq_entry_t*)wdog, &g_wdactivelist); + } + else + { + sq_addafter((FAR sq_entry_t*)prev, (FAR sq_entry_t*)wdog, + &g_wdactivelist); + } + } + + /* The new watchdog delay time is greater than the curr delay time, + * so the new wdog must be inserted after the curr. This only occurs + * if the wdog is to be added to the end of the list. + */ + + else + { + delay -= now; + if (!curr->next) + { + sq_addlast((FAR sq_entry_t*)wdog, &g_wdactivelist); + } + else + { + next = curr->next; + next->lag -= delay; + sq_addafter((FAR sq_entry_t*)curr, (FAR sq_entry_t*)wdog, + &g_wdactivelist); + } + } + } + + /* Put the lag into the watchdog structure and mark it as active. */ + + wdog->lag = delay; + wdog->active = true; + + irqrestore(saved_state); + return OK; +} + +/**************************************************************************** + * Name: wd_timer + * + * Description: + * This function is called from the timer interrupt handler to determine + * if it is time to execute a watchdog function. If so, the watchdog + * function will be executed in the context of the timer interrupt handler. + * + * Parameters: + * None + * + * Return Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +void wd_timer(void) +{ + FAR wdog_t *wdog; + + /* Check if there are any active watchdogs to process */ + + if (g_wdactivelist.head) + { + /* There are. Decrement the lag counter */ + + --(((FAR wdog_t*)g_wdactivelist.head)->lag); + + /* Check if the watchdog at the head of the list is ready to run */ + + if (((FAR wdog_t*)g_wdactivelist.head)->lag <= 0) + { + /* Process the watchdog at the head of the list as well as any + * other watchdogs that became ready to run at this time + */ + + while (g_wdactivelist.head && + ((FAR wdog_t*)g_wdactivelist.head)->lag <= 0) + { + /* Remove the watchdog from the head of the list */ + + wdog = (FAR wdog_t*)sq_remfirst(&g_wdactivelist); + + /* If there is another watchdog behind this one, update its + * its lag (this shouldn't be necessary). + */ + + if (g_wdactivelist.head) + { + ((FAR wdog_t*)g_wdactivelist.head)->lag += wdog->lag; + } + + /* Indicate that the watchdog is no longer active. */ + + wdog->active = false; + + /* Execute the watchdog function */ + + up_setpicbase(wdog->picbase); + switch (wdog->argc) + { + default: +#ifdef CONFIG_DEBUG + PANIC(OSERR_INTERNAL); +#endif + case 0: + (*((wdentry0_t)(wdog->func)))(0); + break; + +#if CONFIG_MAX_WDOGPARMS > 0 + case 1: + (*((wdentry1_t)(wdog->func)))(1, wdog->parm[0]); + break; +#endif +#if CONFIG_MAX_WDOGPARMS > 1 + case 2: + (*((wdentry2_t)(wdog->func)))(2, + wdog->parm[0], wdog->parm[1]); + break; +#endif +#if CONFIG_MAX_WDOGPARMS > 2 + case 3: + (*((wdentry3_t)(wdog->func)))(3, + wdog->parm[0], wdog->parm[1], + wdog->parm[2]); + break; +#endif +#if CONFIG_MAX_WDOGPARMS > 3 + case 4: + (*((wdentry4_t)(wdog->func)))(4, + wdog->parm[0], wdog->parm[1], + wdog->parm[2] ,wdog->parm[3]); + break; +#endif + } + } + } + } +} diff --git a/nuttx/sched/work_cancel.c b/nuttx/sched/work_cancel.c new file mode 100644 index 000000000..55df86f44 --- /dev/null +++ b/nuttx/sched/work_cancel.c @@ -0,0 +1,127 @@ +/**************************************************************************** + * sched/work_cancel.c + * + * Copyright (C) 2009-2010, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include + +#include +#include + +#include "work_internal.h" + +#ifdef CONFIG_SCHED_WORKQUEUE + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: work_cancel + * + * Description: + * Cancel previously queued work. This removes work from the work queue. + * After work has been canceled, it may be re-queue by calling work_queue() + * again. + * + * Input parameters: + * qid - The work queue ID + * work - The previously queue work structure to cancel + * + * Returned Value: + * Zero on success, a negated errno on failure + * + ****************************************************************************/ + +int work_cancel(int qid, FAR struct work_s *work) +{ + FAR struct wqueue_s *wqueue = &g_work[qid]; + irqstate_t flags; + + DEBUGASSERT(work != NULL && (unsigned)qid < NWORKERS); + + /* Cancelling the work is simply a matter of removing the work structure + * from the work queue. This must be done with interrupts disabled because + * new work is typically added to the work queue from interrupt handlers. + */ + + flags = irqsave(); + if (work->worker != NULL) + { + /* A little test of the integrity of the work queue */ + + DEBUGASSERT(work->dq.flink ||(FAR dq_entry_t *)work == wqueue->q.tail); + DEBUGASSERT(work->dq.blink ||(FAR dq_entry_t *)work == wqueue->q.head); + + /* Remove the entry from the work queue and make sure that it is + * mark as availalbe (i.e., the worker field is nullified). + */ + + dq_rem((FAR dq_entry_t *)work, &wqueue->q); + work->worker = NULL; + } + + irqrestore(flags); + return OK; +} + +#endif /* CONFIG_SCHED_WORKQUEUE */ diff --git a/nuttx/sched/work_internal.h b/nuttx/sched/work_internal.h new file mode 100644 index 000000000..7f6c1a937 --- /dev/null +++ b/nuttx/sched/work_internal.h @@ -0,0 +1,114 @@ +/**************************************************************************** + * sched/work_internal.h + * + * Copyright (C) 2009-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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. + * + ****************************************************************************/ + +#ifndef __SCHED_WORK_INTERNAL_H +#define __SCHED_WORK_INTERNAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#ifdef CONFIG_SCHED_WORKQUEUE + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +#ifdef CONFIG_DISABLE_SIGNALS +# warning "Worker thread support requires signals" +#endif + +#ifdef CONFIG_SCHED_LPWORK +# define NWORKERS 2 +#else +# define NWORKERS 1 +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/* This structure defines the state on one work queue */ + +struct wqueue_s +{ + pid_t pid; /* The task ID of the worker thread */ + struct dq_queue_s q; /* The queue of pending work */ +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* The state of each work queue */ + +extern struct wqueue_s g_work[NWORKERS]; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: work_hpthread and work_lpthread + * + * Description: + * These are the main worker threads that performs actions placed on the + * work lists. One thread also performs periodic garbage collection (that + * is performed by the idle thread if CONFIG_SCHED_WORKQUEUE is not defined). + * + * Input parameters: + * argc, argv (not used) + * + * Returned Value: + * Does not return + * + ****************************************************************************/ + +int work_hpthread(int argc, char *argv[]); + +#ifdef CONFIG_SCHED_LPWORK +int work_lpthread(int argc, char *argv[]); +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* CONFIG_SCHED_WORKQUEUE */ +#endif /* __SCHED_WORK_INTERNAL_H */ diff --git a/nuttx/sched/work_queue.c b/nuttx/sched/work_queue.c new file mode 100644 index 000000000..075f08a4d --- /dev/null +++ b/nuttx/sched/work_queue.c @@ -0,0 +1,138 @@ +/**************************************************************************** + * sched/work_queue.c + * + * Copyright (C) 2009-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "work_internal.h" + +#ifdef CONFIG_SCHED_WORKQUEUE + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: work_queue + * + * Description: + * Queue work to be performed at a later time. All queued work will be + * performed on the worker thread of of execution (not the caller's). + * + * The work structure is allocated by caller, but completely managed by + * the work queue logic. The caller should never modify the contents of + * the work queue structure; the caller should not call work_queue() + * again until either (1) the previous work has been performed and removed + * from the queue, or (2) work_cancel() has been called to cancel the work + * and remove it from the work queue. + * + * Input parameters: + * qid - The work queue ID (index) + * work - The work structure to queue + * worker - The worker callback to be invoked. The callback will invoked + * on the worker thread of execution. + * arg - The argument that will be passed to the workder callback when + * int is invoked. + * delay - Delay (in clock ticks) from the time queue until the worker + * is invoked. Zero means to perform the work immediately. + * + * Returned Value: + * Zero on success, a negated errno on failure + * + ****************************************************************************/ + +int work_queue(int qid, FAR struct work_s *work, worker_t worker, + FAR void *arg, uint32_t delay) +{ + FAR struct wqueue_s *wqueue = &g_work[qid]; + irqstate_t flags; + + DEBUGASSERT(work != NULL && (unsigned)qid < NWORKERS); + + /* First, initialize the work structure */ + + work->worker = worker; /* Work callback */ + work->arg = arg; /* Callback argument */ + work->delay = delay; /* Delay until work performed */ + + /* Now, time-tag that entry and put it in the work queue. This must be + * done with interrupts disabled. This permits this function to be called + * from with task logic or interrupt handlers. + */ + + flags = irqsave(); + work->qtime = clock_systimer(); /* Time work queued */ + + dq_addlast((FAR dq_entry_t *)work, &wqueue->q); + kill(wqueue->pid, SIGWORK); /* Wake up the worker thread */ + + irqrestore(flags); + return OK; +} + +#endif /* CONFIG_SCHED_WORKQUEUE */ diff --git a/nuttx/sched/work_signal.c b/nuttx/sched/work_signal.c new file mode 100644 index 000000000..6e6838c69 --- /dev/null +++ b/nuttx/sched/work_signal.c @@ -0,0 +1,96 @@ +/**************************************************************************** + * sched/work_signal.c + * + * Copyright (C) 2009-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include + +#include + +#include "work_internal.h" + +#ifdef CONFIG_SCHED_WORKQUEUE + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ +/**************************************************************************** + * Name: work_signal + * + * Description: + * Signal the worker thread to process the work queue now. This function + * is used internally by the work logic but could also be used by the + * user to force an immediate re-assessment of pending work. + * + * Input parameters: + * qid - The work queue ID + * + * Returned Value: + * Zero on success, a negated errno on failure + * + ****************************************************************************/ + +int work_signal(int qid) +{ + DEBUGASSERT((unsigned)qid < NWORKERS); + return kill(g_work[qid].pid, SIGWORK); +} + +#endif /* CONFIG_SCHED_WORKQUEUE */ diff --git a/nuttx/sched/work_thread.c b/nuttx/sched/work_thread.c new file mode 100644 index 000000000..abd86f771 --- /dev/null +++ b/nuttx/sched/work_thread.c @@ -0,0 +1,256 @@ +/**************************************************************************** + * sched/work_thread.c + * + * Copyright (C) 2009-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "os_internal.h" +#include "work_internal.h" + +#ifdef CONFIG_SCHED_WORKQUEUE + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/* The state of each work queue */ + +struct wqueue_s g_work[NWORKERS]; + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: work_process + * + * Description: + * This is the logic that performs actions placed on any work list. + * + * Input parameters: + * wqueue - Describes the work queue to be processed + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void work_process(FAR struct wqueue_s *wqueue) +{ + volatile FAR struct work_s *work; + worker_t worker; + irqstate_t flags; + FAR void *arg; + uint32_t elapsed; + uint32_t remaining; + uint32_t next; + + /* Then process queued work. We need to keep interrupts disabled while + * we process items in the work list. + */ + + next = CONFIG_SCHED_WORKPERIOD / USEC_PER_TICK; + flags = irqsave(); + work = (FAR struct work_s *)wqueue->q.head; + while (work) + { + /* Is this work ready? It is ready if there is no delay or if + * the delay has elapsed. qtime is the time that the work was added + * to the work queue. It will always be greater than or equal to + * zero. Therefore a delay of zero will always execute immediately. + */ + + elapsed = clock_systimer() - work->qtime; + if (elapsed >= work->delay) + { + /* Remove the ready-to-execute work from the list */ + + (void)dq_rem((struct dq_entry_s *)work, &wqueue->q); + + /* Extract the work description from the entry (in case the work + * instance by the re-used after it has been de-queued). + */ + + worker = work->worker; + arg = work->arg; + + /* Mark the work as no longer being queued */ + + work->worker = NULL; + + /* Do the work. Re-enable interrupts while the work is being + * performed... we don't have any idea how long that will take! + */ + + irqrestore(flags); + worker(arg); + + /* Now, unfortunately, since we re-enabled interrupts we don't + * know the state of the work list and we will have to start + * back at the head of the list. + */ + + flags = irqsave(); + work = (FAR struct work_s *)wqueue->q.head; + } + else + { + /* This one is not ready.. will it be ready before the next + * scheduled wakeup interval? + */ + + remaining = elapsed - work->delay; + if (remaining < next) + { + /* Yes.. Then schedule to wake up when the work is ready */ + + next = remaining; + } + + /* Then try the next in the list. */ + + work = (FAR struct work_s *)work->dq.flink; + } + } + + /* Wait awhile to check the work list. We will wait here until either + * the time elapses or until we are awakened by a signal. + */ + + usleep(next * USEC_PER_TICK); + irqrestore(flags); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ +/**************************************************************************** + * Name: work_hpthread and work_lpthread + * + * Description: + * These are the main worker threads that performs actions placed on the + * work lists. One thread also performs periodic garbage collection (that + * is performed by the idle thread if CONFIG_SCHED_WORKQUEUE is not defined). + * + * Input parameters: + * argc, argv (not used) + * + * Returned Value: + * Does not return + * + ****************************************************************************/ + +int work_hpthread(int argc, char *argv[]) +{ + /* Loop forever */ + + for (;;) + { + /* First, perform garbage collection. This cleans-up memory de-allocations + * that were queued because they could not be freed in that execution + * context (for example, if the memory was freed from an interrupt handler). + * NOTE: If the work thread is disabled, this clean-up is performed by + * the IDLE thread (at a very, very lower priority). + */ + +#ifdef CONFIG_SCHED_LPWORK + sched_garbagecollection(); +#endif + + /* Then process queued work. We need to keep interrupts disabled while + * we process items in the work list. + */ + + work_process(&g_work[HPWORK]); + } + + return OK; /* To keep some compilers happy */ +} + +#ifdef CONFIG_SCHED_LPWORK +int work_lpthread(int argc, char *argv[]) +{ + /* Loop forever */ + + for (;;) + { + /* First, perform garbage collection. This cleans-up memory de-allocations + * that were queued because they could not be freed in that execution + * context (for example, if the memory was freed from an interrupt handler). + * NOTE: If the work thread is disabled, this clean-up is performed by + * the IDLE thread (at a very, very lower priority). + */ + + sched_garbagecollection(); + + /* Then process queued work. We need to keep interrupts disabled while + * we process items in the work list. + */ + + work_process(&g_work[LPWORK]); + } + + return OK; /* To keep some compilers happy */ +} + +#endif /* CONFIG_SCHED_LPWORK */ + +#endif /* CONFIG_SCHED_WORKQUEUE */ -- cgit v1.2.3