diff options
author | davidxu <davidxu@FreeBSD.org> | 2006-03-08 23:47:04 +0000 |
---|---|---|
committer | davidxu <davidxu@FreeBSD.org> | 2006-03-08 23:47:04 +0000 |
commit | d119bdaa7ac2143c8eb151df28b393d38361ea0c (patch) | |
tree | cc54896c2c387012a7297c8bf17dddeff6b1c0fb /lib/libthr | |
parent | 2e0e03c06ff6c78e7d6f269c98e20d8e2eeb58dc (diff) | |
download | FreeBSD-src-d119bdaa7ac2143c8eb151df28b393d38361ea0c.zip FreeBSD-src-d119bdaa7ac2143c8eb151df28b393d38361ea0c.tar.gz |
Remove mqueue and timer, now they are in librt.
Diffstat (limited to 'lib/libthr')
-rw-r--r-- | lib/libthr/pthread.map | 8 | ||||
-rw-r--r-- | lib/libthr/thread/thr_timer.c | 517 |
2 files changed, 0 insertions, 525 deletions
diff --git a/lib/libthr/pthread.map b/lib/libthr/pthread.map index ec7017d..d6d1fcd 100644 --- a/lib/libthr/pthread.map +++ b/lib/libthr/pthread.map @@ -2,14 +2,12 @@ LIBTHREAD_1_0 { global: ___creat; - ___mq_close; __accept; __close; __connect; __error; __fcntl; __fsync; - __mq_notify; __msync; __nanosleep; __open; @@ -34,7 +32,6 @@ global: _aio_suspend; _execve; _fork; - _mq_notify; _nanosleep; _pause; _pselect; @@ -181,8 +178,6 @@ global: _spinunlock; _system; _tcdrain; - _timer_create; - _timer_delete; _usleep; _vfork; _wait; @@ -196,7 +191,6 @@ global: fcntl; fork; fsync; - mq_notify; msync; nanosleep; open; @@ -349,8 +343,6 @@ global: sleep; system; tcdrain; - timer_create; - timer_delete; usleep; vfork; wait; diff --git a/lib/libthr/thread/thr_timer.c b/lib/libthr/thread/thr_timer.c deleted file mode 100644 index 7e3fba0..0000000 --- a/lib/libthr/thread/thr_timer.c +++ /dev/null @@ -1,517 +0,0 @@ -/* - * Copyright (c) 2005 David Xu <davidxu@freebsd.org> - * All rights reserved. - * - * 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 unmodified, 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. - * - * $FreeBSD$ - * - */ - -#include <sys/cdefs.h> -#include <sys/types.h> - -#include <mqueue.h> -#include <time.h> -#include <setjmp.h> -#include <stdlib.h> -#include <string.h> - -#include "thr_private.h" - -struct thread_node { - struct pthread_attr tn_attr; - TAILQ_ENTRY(thread_node)tn_link; - pthread_t tn_thread; - int tn_refcount; - int tn_exit; - jmp_buf tn_jbuf; - struct rtobj_node * tn_curobj; -}; - -struct rtobj_node { - LIST_ENTRY(rtobj_node) rt_link; - int rt_type; - union sigval rt_value; - void * rt_func; - umtx_t rt_flags; - union { - int _timerid; - int _mqd; - } _rt_id; - int rt_gen; - struct thread_node * rt_tn; -}; - -#define rt_timerid _rt_id._timerid -#define rt_mqd _rt_id._mqd - -LIST_HEAD(rtobj_hash_head, rtobj_node); -#define HASH_QUEUES 17 -#define HASH(t, id) ((((id) << 3) + (t)) % HASH_QUEUES) -static struct rtobj_hash_head rtobj_hash[HASH_QUEUES]; -static int generation; -static umtx_t hash_lock; -static TAILQ_HEAD(,thread_node) threads; -static umtx_t threads_lock; - -static struct thread_node *thread_create(pthread_attr_t *); -static void thread_release(struct thread_node *); -static struct rtobj_node *rtobj_find(int, int); -static int rtobj_register(struct rtobj_node *); -static int rtobj_delete(int, int); -static int rtobj_delete_obj(struct rtobj_node *); -static void * service_loop(void *); -static void timer_dispatch(struct rtobj_node *p, int); - -extern int __sys_timer_create(clockid_t, struct sigevent *, timer_t *); -extern int __sys_timer_delete(timer_t); -extern int __sys_mq_notify(mqd_t mqdes, const struct sigevent *); -extern int __mq_close(mqd_t mqd); - -__weak_reference(__timer_create, timer_create); -__weak_reference(__timer_create, _timer_create); -__weak_reference(__timer_delete, timer_delete); -__weak_reference(__timer_delete, _timer_delete); -__weak_reference(__mq_notify, mq_notify); -__weak_reference(__mq_notify, _mq_notify); -__weak_reference(___mq_close, mq_close); -__weak_reference(___mq_close, _mq_close); - -#define SIGSERVICE (SIGCANCEL+1) - -#define RT_WORKING 0x01 -#define RT_WANTED 0x02 - -#define HASH_LOCK(t) THR_LOCK_ACQUIRE((t), &hash_lock) -#define HASH_UNLOCK(t) THR_LOCK_RELEASE((t), &hash_lock) - -#define THREADS_LOCK(t) THR_LOCK_ACQUIRE((t), &threads_lock) -#define THREADS_UNLOCK(t) THR_LOCK_RELEASE((t), &threads_lock) - -void -_thr_timer_init(void) -{ - int i; - - _thr_umtx_init(&hash_lock); - _thr_umtx_init(&threads_lock); - for (i = 0; i < HASH_QUEUES; ++i) - LIST_INIT(&rtobj_hash[i]); - TAILQ_INIT(&threads); -} - -static struct rtobj_node * -rtobj_alloc(int type, const struct sigevent *evp) -{ - struct rtobj_node *obj; - - obj = calloc(1, sizeof(*obj)); - if (obj != NULL) { - obj->rt_value = evp->sigev_value; - obj->rt_func = evp->sigev_notify_function; - obj->rt_gen = atomic_fetchadd_int(&generation, 1); - obj->rt_type = type; - } - - return (obj); -} - -static __inline void -rtobj_free(struct rtobj_node *obj) -{ - free(obj); -} - -static struct rtobj_node * -rtobj_find(int type, int id) -{ - struct rtobj_node *obj; - int chain = HASH(type, id); - - LIST_FOREACH(obj, &rtobj_hash[chain], rt_link) { - if (obj->rt_type == type && obj->rt_mqd == id) - break; - } - return (obj); -} - -static int -rtobj_register(struct rtobj_node *obj) -{ - int chain = HASH(obj->rt_type, obj->rt_mqd); - - LIST_INSERT_HEAD(&rtobj_hash[chain], obj, rt_link); - return (0); -} - -static int -rtobj_delete(int type, int id) -{ - struct rtobj_node *obj; - - obj = rtobj_find(type, id); - if (obj != NULL) - return (rtobj_delete_obj(obj)); - return (0); -} - -static int -rtobj_delete_obj(struct rtobj_node *obj) -{ - struct pthread *curthread = _get_curthread(); - umtx_t flags; - - LIST_REMOVE(obj, rt_link); - /* If the timer is servicing, allow it to complete. */ - while ((flags = obj->rt_flags) & RT_WORKING) { - obj->rt_flags |= RT_WANTED; - HASH_UNLOCK(curthread); - _thr_umtx_wait(&obj->rt_flags, flags, NULL); - HASH_LOCK(curthread); - } - HASH_UNLOCK(curthread); - /* - * Drop reference count of servicing thread, - * may free the thread. - */ - thread_release(obj->rt_tn); - rtobj_free(obj); - - HASH_LOCK(curthread); - return (0); -} - -/* - * Purpose of the function is to implement POSIX timer's - * SEGEV_THREAD notification mechanism. - */ -int -__timer_create(clockid_t clockid, struct sigevent *evp, timer_t *timerid) -{ - struct sigevent ev; - struct rtobj_node *obj; - struct pthread *curthread; - int ret, err; - - /* Call syscall directly if it is not SIGEV_THREAD */ - if (evp == NULL || evp->sigev_notify != SIGEV_THREAD) - return (__sys_timer_create(clockid, evp, timerid)); - - /* Otherwise, do all magical things. */ - obj = rtobj_alloc(SI_TIMER, evp); - if (obj == NULL) { - errno = EAGAIN; - return (-1); - } - obj->rt_tn = thread_create(evp->sigev_notify_attributes); - if (obj->rt_tn == NULL) { - rtobj_free(obj); - errno = EAGAIN; - return (-1); - } - - /* - * Build a new sigevent, and tell kernel to deliver SIGSERVICE - * signal to the new thread. - */ - ev.sigev_notify = SIGEV_THREAD_ID; - ev.sigev_signo = SIGSERVICE; - ev.sigev_notify_thread_id = (lwpid_t)obj->rt_tn->tn_thread->tid; - ev.sigev_value.sival_int = obj->rt_gen; - ret = __sys_timer_create(clockid, &ev, &obj->rt_timerid); - if (ret != 0) { - err = errno; - thread_release(obj->rt_tn); - rtobj_free(obj); - errno = err; - return (-1); - } - curthread = _get_curthread(); - HASH_LOCK(curthread); - rtobj_register(obj); - HASH_UNLOCK(curthread); - *timerid = obj->rt_timerid; - return (0); -} - -int -__timer_delete(timer_t timerid) -{ - struct pthread *curthread = _get_curthread(); - - HASH_LOCK(curthread); - rtobj_delete(SI_TIMER, timerid); - HASH_UNLOCK(curthread); - return (__sys_timer_delete(timerid)); -} - -typedef void (*timer_func)(union sigval val, int timerid, int overrun); - -static void -timer_dispatch(struct rtobj_node *obj, int overrun) -{ - timer_func f = obj->rt_func; - - f(obj->rt_value, obj->rt_timerid, overrun); -} - -int -___mq_close(mqd_t mqd) -{ - struct pthread *curthread; - int ret; - - curthread = _get_curthread(); - HASH_LOCK(curthread); - rtobj_delete(SI_MESGQ, mqd); - ret = __mq_close(mqd); - HASH_UNLOCK(curthread); - return (ret); -} - -int -__mq_notify(mqd_t mqd, const struct sigevent *evp) -{ - struct sigevent ev; - struct rtobj_node *obj; - struct pthread *curthread; - int ret, err; - - curthread = _get_curthread(); - - HASH_LOCK(curthread); - rtobj_delete(SI_MESGQ, mqd); - if (evp == NULL || evp->sigev_notify != SIGEV_THREAD) { - ret = __sys_mq_notify(mqd, evp); - HASH_UNLOCK(curthread); - return (ret); - } - HASH_UNLOCK(curthread); - - obj = rtobj_alloc(SI_MESGQ, evp); - if (obj == NULL) { - errno = EAGAIN; - return (-1); - } - obj->rt_tn = thread_create(evp->sigev_notify_attributes); - if (obj->rt_tn == NULL) { - rtobj_free(obj); - errno = EAGAIN; - return (-1); - } - obj->rt_mqd = mqd; - /* - * Build a new sigevent, and tell kernel to deliver SIGSERVICE - * signal to the new thread. - */ - ev.sigev_notify = SIGEV_THREAD_ID; - ev.sigev_signo = SIGSERVICE; - ev.sigev_notify_thread_id = (lwpid_t)obj->rt_tn->tn_thread->tid; - ev.sigev_value.sival_int = obj->rt_gen; - HASH_LOCK(curthread); - ret = __sys_mq_notify(mqd, &ev); - if (ret != 0) { - err = errno; - HASH_UNLOCK(curthread); - thread_release(obj->rt_tn); - rtobj_free(obj); - errno = err; - return (-1); - } - rtobj_register(obj); - HASH_UNLOCK(curthread); - return (0); -} - -typedef void (*mq_func)(union sigval val, int mqd); - -static void -mq_dispatch(struct rtobj_node *obj) -{ - mq_func f = obj->rt_func; - - f(obj->rt_value, obj->rt_mqd); -} - -static struct thread_node * -thread_create(pthread_attr_t *pattr) -{ - pthread_attr_t attr; - struct pthread *curthread; - struct thread_node *tn; - int ret; - - curthread = _get_curthread(); - pthread_attr_init(&attr); - if (pattr != NULL) { - *attr = **(pthread_attr_t *)pattr; - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - } - - THREADS_LOCK(curthread); - /* Search a thread matching the required pthread_attr. */ - TAILQ_FOREACH(tn, &threads, tn_link) { - if (attr->stackaddr_attr == NULL) { - if (attr->sched_policy == tn->tn_attr.sched_policy && - attr->sched_inherit == tn->tn_attr.sched_inherit && - attr->prio == tn->tn_attr.prio && - attr->stacksize_attr == tn->tn_attr.stacksize_attr && - attr->guardsize_attr == tn->tn_attr.guardsize_attr && - ((attr->flags & PTHREAD_SCOPE_SYSTEM) == - (tn->tn_attr.flags & PTHREAD_SCOPE_SYSTEM))) - break; - } else { - /* - * Reuse the thread if it has same stack address, - * because two threads can not run on same stack. - */ - if (attr->stackaddr_attr == tn->tn_attr.stackaddr_attr) - break; - } - } - if (tn != NULL) { - tn->tn_refcount++; - THREADS_UNLOCK(curthread); - pthread_attr_destroy(&attr); - return (tn); - } - tn = malloc(sizeof(*tn)); - tn->tn_refcount = 1; - tn->tn_exit = 0; - tn->tn_attr = *attr; - tn->tn_curobj = NULL; - _thr_signal_block(curthread); /* SIGSERVICE is also blocked. */ - TAILQ_INSERT_TAIL(&threads, tn, tn_link); - ret = _pthread_create(&tn->tn_thread, &attr, service_loop, tn); - _thr_signal_unblock(curthread); - if (ret != 0) { - TAILQ_REMOVE(&threads, tn, tn_link); - free(tn); - tn = NULL; - } - THREADS_UNLOCK(curthread); - pthread_attr_destroy(&attr); - return (tn); -} - -static void -thread_release(struct thread_node *tn) -{ - struct pthread *curthread = _get_curthread(); - - THREADS_LOCK(curthread); - tn->tn_refcount--; -#if 0 - if (tn->tn_refcount == 0) { - struct pthread *th; - tn->tn_exit = 1; - th = tn->tn_thread; - _thr_send_sig(th, SIGSERVICE); - TAILQ_REMOVE(&threads, tn, tn_link); - } else -#endif - tn = NULL; - THREADS_UNLOCK(curthread); - if (tn != NULL) - free(tn); -} - -/* - * This function is called if user callback calls - * pthread_exit() or pthread_cancel() for the thread. - */ -static void -thread_cleanup(void *arg) -{ - struct pthread *curthread = _get_curthread(); - struct thread_node *tn = arg; - - if (tn->tn_exit == 0) { - /* broken user code is killing us. */ - if (tn->tn_curobj != NULL) { - HASH_LOCK(curthread); - tn->tn_curobj->rt_flags &= ~RT_WORKING; - if (tn->tn_curobj->rt_flags & RT_WANTED) - _thr_umtx_wake(&tn->tn_curobj->rt_flags, INT_MAX); - HASH_UNLOCK(curthread); - } - atomic_clear_int(&curthread->cancelflags, THR_CANCEL_EXITING); - longjmp(tn->tn_jbuf, 1); - } -} - -static void * -service_loop(void *arg) -{ - siginfo_t si; - sigset_t set; - struct thread_node *tn; - struct pthread *curthread; - struct rtobj_node *obj; - - tn = arg; - curthread = _get_curthread(); - /* - * Service thread should not be killed by callback, if user - * tries to do so, the thread will be restarted. - */ - setjmp(tn->tn_jbuf); - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); - sigemptyset(&set); - sigaddset(&set, SIGCANCEL); - __sys_sigprocmask(SIG_UNBLOCK, &set, NULL); - sigdelset(&set, SIGCANCEL); - sigaddset(&set, SIGSERVICE); - THR_CLEANUP_PUSH(curthread, thread_cleanup, tn); - while (tn->tn_exit == 0) { - if (__predict_false(__sys_sigwaitinfo(&set, &si) == -1 || - (si.si_code != SI_TIMER && si.si_code != SI_MESGQ))) - continue; - HASH_LOCK(curthread); - obj = rtobj_find(si.si_code, si.si_timerid); - if (obj && (obj->rt_gen == si.si_value.sival_int)) { - obj->rt_flags |= RT_WORKING; - HASH_UNLOCK(curthread); - tn->tn_curobj = obj; - if (si.si_code == SI_TIMER) - timer_dispatch(obj, si.si_overrun); - else if (si.si_code == SI_MESGQ) - mq_dispatch(obj); - tn->tn_curobj = NULL; - HASH_LOCK(curthread); - obj->rt_flags &= ~RT_WORKING; - if (obj->rt_flags & RT_WANTED) - _thr_umtx_wake(&obj->rt_flags, INT_MAX); - else if (si.si_code == SI_MESGQ) { - /* - * mq_notify is oneshot event, should remove - * atomatically by the thread. - */ - rtobj_delete_obj(obj); - } - } - HASH_UNLOCK(curthread); - } - THR_CLEANUP_POP(curthread, 0); - return (0); -} |