source: mainline/kernel/generic/src/synch/syswaitq.c@ 6874bd2

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 6874bd2 was 6874bd2, checked in by Jakub Jermar <jakub@…>, 7 years ago

Fix build after rebase

  • Property mode set to 100644
File size: 5.0 KB
Line 
1/*
2 * Copyright (c) 2018 Jakub Jermar
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup kernel_sync
30 * @{
31 */
32
33/**
34 * @file
35 * @brief Wrapper for using wait queue as a kobject.
36 */
37
38#include <synch/syswaitq.h>
39#include <synch/waitq.h>
40#include <abi/cap.h>
41#include <cap/cap.h>
42#include <mm/slab.h>
43#include <proc/task.h>
44#include <syscall/copy.h>
45
46#include <stdint.h>
47#include <stdlib.h>
48
49static slab_cache_t *waitq_cache;
50
51static void waitq_destroy(void *arg)
52{
53 waitq_t *wq = (waitq_t *) arg;
54 slab_free(waitq_cache, wq);
55}
56
57static kobject_ops_t waitq_kobject_ops = {
58 .destroy = waitq_destroy
59};
60
61static bool waitq_cap_cleanup_cb(cap_t *cap, void *arg)
62{
63 kobject_t *kobj = cap_unpublish(cap->task, cap->handle,
64 KOBJECT_TYPE_WAITQ);
65 kobject_put(kobj);
66 cap_free(cap->task, cap->handle);
67 return true;
68}
69
70/** Initialize the user waitq subsystem */
71void sys_waitq_init(void)
72{
73 waitq_cache = slab_cache_create("waitq_t", sizeof(waitq_t), 0, NULL,
74 NULL, 0);
75}
76
77/** Clean-up all waitq capabilities held by the exiting task */
78void sys_waitq_task_cleanup(void)
79{
80 caps_apply_to_kobject_type(TASK, KOBJECT_TYPE_WAITQ,
81 waitq_cap_cleanup_cb, NULL);
82}
83
84/** Create a waitq for the current task
85 *
86 * @param[out] whandle Userspace address of the destination buffer that will
87 * receive the allocated waitq capability.
88 *
89 * @return Error code.
90 */
91sys_errno_t sys_waitq_create(cap_waitq_handle_t *whandle)
92{
93 waitq_t *wq = slab_alloc(waitq_cache, FRAME_ATOMIC);
94 if (!wq)
95 return (sys_errno_t) ENOMEM;
96 waitq_initialize(wq);
97
98 kobject_t *kobj = (kobject_t *) malloc(sizeof(kobject_t));
99 if (!kobj) {
100 slab_free(waitq_cache, wq);
101 return (sys_errno_t) ENOMEM;
102 }
103 kobject_initialize(kobj, KOBJECT_TYPE_WAITQ, wq, &waitq_kobject_ops);
104
105 cap_handle_t handle;
106 errno_t rc = cap_alloc(TASK, &handle);
107 if (rc != EOK) {
108 slab_free(waitq_cache, wq);
109 free(kobj);
110 return (sys_errno_t) rc;
111 }
112
113 rc = copy_to_uspace(whandle, &handle, sizeof(handle));
114 if (rc != EOK) {
115 cap_free(TASK, handle);
116 free(kobj);
117 slab_free(waitq_cache, wq);
118 return (sys_errno_t) rc;
119 }
120
121 cap_publish(TASK, handle, kobj);
122
123 return (sys_errno_t) EOK;
124}
125
126/** Destroy a waitq
127 *
128 * @param whandle Waitq capability handle of the waitq to be destroyed.
129 *
130 * @return Error code.
131 */
132sys_errno_t sys_waitq_destroy(cap_waitq_handle_t whandle)
133{
134 kobject_t *kobj = cap_unpublish(TASK, whandle, KOBJECT_TYPE_WAITQ);
135 if (!kobj)
136 return (sys_errno_t) ENOENT;
137 kobject_put(kobj);
138 cap_free(TASK, whandle);
139 return EOK;
140}
141
142/** Sleep in the waitq
143 *
144 * @param whandle Waitq capability handle of the waitq in which to sleep.
145 * @param timeout Timeout in microseconds.
146 * @param flags Flags from SYNCH_FLAGS_* family. SYNCH_FLAGS_INTERRUPTIBLE is
147 * always implied.
148 *
149 * @return Error code.
150 */
151sys_errno_t sys_waitq_sleep(cap_waitq_handle_t whandle, uint32_t timeout,
152 unsigned int flags)
153{
154 kobject_t *kobj = kobject_get(TASK, whandle, KOBJECT_TYPE_WAITQ);
155 if (!kobj)
156 return (sys_errno_t) ENOENT;
157
158#ifdef CONFIG_UDEBUG
159 udebug_stoppable_begin();
160#endif
161
162 errno_t rc = waitq_sleep_timeout(kobj->waitq, timeout,
163 SYNCH_FLAGS_INTERRUPTIBLE | flags, NULL);
164
165#ifdef CONFIG_UDEBUG
166 udebug_stoppable_end();
167#endif
168
169 kobject_put(kobj);
170
171 return (sys_errno_t) rc;
172}
173
174/** Wakeup a thread sleeping in the waitq
175 *
176 * @param whandle Waitq capability handle of the waitq to invoke wakeup on.
177 *
178 * @return Error code.
179 */
180sys_errno_t sys_waitq_wakeup(cap_waitq_handle_t whandle)
181{
182 kobject_t *kobj = kobject_get(TASK, whandle, KOBJECT_TYPE_WAITQ);
183 if (!kobj)
184 return (sys_errno_t) ENOENT;
185
186 waitq_wakeup(kobj->waitq, WAKEUP_FIRST);
187
188 kobject_put(kobj);
189 return (sys_errno_t) EOK;
190}
191
192/** @}
193 */
Note: See TracBrowser for help on using the repository browser.