base/ipc/bits/bits.c

Go to the documentation of this file.
00001 /* 00002 * Copyright (C) 1999-2003 Paolo Mantegazza <mantegazza@aero.polimi.it> 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License as 00006 * published by the Free Software Foundation; either version 2 of the 00007 * License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software 00016 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00017 */ 00018 00019 #include <linux/kernel.h> 00020 #include <linux/module.h> 00021 #include <linux/errno.h> 00022 #include <linux/config.h> 00023 #include <linux/version.h> 00024 #include <asm/uaccess.h> 00025 00026 #include <rtai_schedcore.h> 00027 #include <rtai_sched.h> 00028 #include <rtai_lxrt.h> 00029 #include <rtai_bits.h> 00030 00031 MODULE_LICENSE("GPL"); 00032 00033 #define MASK0(x) ((unsigned long *)&(x))[0] 00034 #define MASK1(x) ((unsigned long *)&(x))[1] 00035 00036 static int all_set(BITS *bits, unsigned long mask) 00037 { 00038 return (bits->mask & mask) == mask; 00039 } 00040 00041 static int any_set(BITS *bits, unsigned long mask) 00042 { 00043 return (bits->mask & mask); 00044 } 00045 00046 static int all_clr(BITS *bits, unsigned long mask) 00047 { 00048 return (~bits->mask & mask) == mask; 00049 } 00050 00051 static int any_clr(BITS *bits, unsigned long mask) 00052 { 00053 return (~bits->mask & mask); 00054 } 00055 00056 static int all_set_and_any_set(BITS *bits, unsigned long masks) 00057 { 00058 return (bits->mask & MASK1(masks)) && (bits->mask & MASK0(masks)) == MASK0(masks); 00059 } 00060 00061 static int all_set_and_all_clr(BITS *bits, unsigned long masks) 00062 { 00063 return (bits->mask & MASK0(masks)) == MASK0(masks) && (~bits->mask & MASK1(masks)) == MASK1(masks); 00064 } 00065 00066 static int all_set_and_any_clr(BITS *bits, unsigned long masks) 00067 { 00068 return (bits->mask & MASK0(masks)) == MASK0(masks) && (~bits->mask & MASK1(masks)); 00069 } 00070 00071 static int any_set_and_all_clr(BITS *bits, unsigned long masks) 00072 { 00073 return (bits->mask & MASK0(masks)) && (~bits->mask & MASK1(masks)) == MASK1(masks); 00074 } 00075 00076 static int any_set_and_any_clr(BITS *bits, unsigned long masks) 00077 { 00078 return (bits->mask & MASK0(masks)) && (~bits->mask & MASK1(masks)); 00079 } 00080 00081 static int all_clr_and_any_clr(BITS *bits, unsigned long masks) 00082 { 00083 return (~bits->mask & MASK1(masks)) && (~bits->mask & MASK0(masks)) == MASK0(masks); 00084 } 00085 00086 static int all_set_or_any_set(BITS *bits, unsigned long masks) 00087 { 00088 return (bits->mask & MASK1(masks)) || (bits->mask & MASK0(masks)) == MASK0(masks); 00089 } 00090 00091 static int all_set_or_all_clr(BITS *bits, unsigned long masks) 00092 { 00093 return (bits->mask & MASK0(masks)) == MASK0(masks) || (~bits->mask & MASK1(masks)) == MASK1(masks); 00094 } 00095 00096 static int all_set_or_any_clr(BITS *bits, unsigned long masks) 00097 { 00098 return (bits->mask & MASK0(masks)) == MASK0(masks) || (~bits->mask & MASK1(masks)); 00099 } 00100 00101 static int any_set_or_all_clr(BITS *bits, unsigned long masks) 00102 { 00103 return (bits->mask & MASK0(masks)) || (~bits->mask & MASK1(masks)) == MASK1(masks); 00104 } 00105 00106 static int any_set_or_any_clr(BITS *bits, unsigned long masks) 00107 { 00108 return (bits->mask & MASK0(masks)) || (~bits->mask & MASK1(masks)); 00109 } 00110 00111 static int all_clr_or_any_clr(BITS *bits, unsigned long masks) 00112 { 00113 return (~bits->mask & MASK1(masks)) || (~bits->mask & MASK0(masks)) == MASK0(masks); 00114 } 00115 00116 static void set_bits(BITS *bits, unsigned long mask) 00117 { 00118 bits->mask |= mask; 00119 } 00120 00121 static void clr_bits(BITS *bits, unsigned long mask) 00122 { 00123 bits->mask &= ~mask; 00124 } 00125 00126 static void set_clr_bits(BITS *bits, unsigned long masks) 00127 { 00128 bits->mask = (bits->mask | MASK0(masks)) & ~MASK1(masks); 00129 } 00130 00131 static void nop_fun(BITS *bits, unsigned long mask) 00132 { 00133 } 00134 00135 static int (*test_fun[])(BITS *, unsigned long) = { 00136 all_set, any_set, all_clr, any_clr, 00137 all_set_and_any_set, all_set_and_all_clr, all_set_and_any_clr, 00138 any_set_and_all_clr, any_set_and_any_clr, 00139 all_clr_and_any_clr, 00140 all_set_or_any_set, all_set_or_all_clr, all_set_or_any_clr, 00141 any_set_or_all_clr, any_set_or_any_clr, 00142 all_clr_or_any_clr 00143 }; 00144 00145 static void (*exec_fun[])(BITS *, unsigned long) = { 00146 set_bits, clr_bits, 00147 set_clr_bits, 00148 nop_fun 00149 }; 00150 00151 void rt_bits_init(BITS *bits, unsigned long mask) 00152 { 00153 bits->magic = RT_BITS_MAGIC; 00154 bits->queue.prev = &(bits->queue); 00155 bits->queue.next = &(bits->queue); 00156 bits->queue.task = 0; 00157 bits->mask = mask; 00158 } 00159 00160 int rt_bits_delete(BITS *bits) 00161 { 00162 unsigned long flags, schedmap; 00163 RT_TASK *task; 00164 QUEUE *q; 00165 00166 if (bits->magic != RT_BITS_MAGIC) { 00167 return BITS_ERR; 00168 } 00169 00170 schedmap = 0; 00171 q = &bits->queue; 00172 flags = rt_global_save_flags_and_cli(); 00173 bits->magic = 0; 00174 while ((q = q->next) != &bits->queue && (task = q->task)) { 00175 rem_timed_task(task); 00176 if (task->state != RT_SCHED_READY && (task->state &= ~(RT_SCHED_SEMAPHORE | RT_SCHED_DELAYED)) == RT_SCHED_READY) { 00177 enq_ready_task(task); 00178 #ifdef CONFIG_SMP 00179 set_bit(task->runnable_on_cpus & 0x1F, &schedmap); 00180 #endif 00181 } 00182 } 00183 RT_SCHEDULE_MAP(schedmap); 00184 rt_global_restore_flags(flags); 00185 return 0; 00186 } 00187 00188 #define TEST_BUF(x, y) do { (x)->retval = (unsigned long)(y); } while (0) 00189 #define TEST_FUN(x) ((long *)((unsigned long)(x)->retval))[0] 00190 #define TEST_MASK(x) ((unsigned long *)((unsigned long)(x)->retval))[1] 00191 00192 unsigned long rt_get_bits(BITS *bits) 00193 { 00194 return bits->mask; 00195 } 00196 00197 int rt_bits_reset(BITS *bits, unsigned long mask) 00198 { 00199 unsigned long flags, schedmap, oldmask; 00200 RT_TASK *task; 00201 QUEUE *q; 00202 00203 if (bits->magic != RT_BITS_MAGIC) { 00204 return BITS_ERR; 00205 } 00206 00207 schedmap = 0; 00208 q = &bits->queue; 00209 flags = rt_global_save_flags_and_cli(); 00210 oldmask = bits->mask; 00211 bits->mask = mask; 00212 while ((q = q->next) != &bits->queue) { 00213 dequeue_blocked(task = q->task); 00214 rem_timed_task(task); 00215 if (task->state != RT_SCHED_READY && (task->state &= ~(RT_SCHED_SEMAPHORE | RT_SCHED_DELAYED)) == RT_SCHED_READY) { 00216 enq_ready_task(task); 00217 #ifdef CONFIG_SMP 00218 set_bit(task->runnable_on_cpus & 0x1F, &schedmap); 00219 #endif 00220 } 00221 } 00222 bits->queue.prev = bits->queue.next = &bits->queue; 00223 RT_SCHEDULE_MAP(schedmap); 00224 rt_global_restore_flags(flags); 00225 return oldmask; 00226 } 00227 00228 unsigned long rt_bits_signal(BITS *bits, int setfun, unsigned long masks) 00229 { 00230 unsigned long flags, schedmap; 00231 RT_TASK *task; 00232 QUEUE *q; 00233 00234 if (bits->magic != RT_BITS_MAGIC) { 00235 return BITS_ERR; 00236 } 00237 00238 schedmap = 0; 00239 q = &bits->queue; 00240 flags = rt_global_save_flags_and_cli(); 00241 exec_fun[setfun](bits, masks); 00242 masks = bits->mask; 00243 while ((q = q->next) != &bits->queue) { 00244 task = q->task; 00245 if (test_fun[TEST_FUN(task)](bits, TEST_MASK(task))) { 00246 dequeue_blocked(task); 00247 rem_timed_task(task); 00248 if (task->state != RT_SCHED_READY && (task->state &= ~(RT_SCHED_SEMAPHORE | RT_SCHED_DELAYED)) == RT_SCHED_READY) { 00249 enq_ready_task(task); 00250 #ifdef CONFIG_SMP 00251 set_bit(task->runnable_on_cpus & 0x1F, &schedmap); 00252 #endif 00253 } 00254 } 00255 } 00256 RT_SCHEDULE_MAP(schedmap); 00257 rt_global_restore_flags(flags); 00258 return masks; 00259 } 00260 00261 int _rt_bits_wait(BITS *bits, int testfun, unsigned long testmasks, int exitfun, unsigned long exitmasks, unsigned long *resulting_mask, int space) 00262 { 00263 RT_TASK *rt_current; 00264 unsigned long flags, mask; 00265 00266 if (bits->magic != RT_BITS_MAGIC) { 00267 return BITS_ERR; 00268 } 00269 00270 flags = rt_global_save_flags_and_cli(); 00271 if (!test_fun[testfun](bits, testmasks)) { 00272 long bits_test[2]; 00273 rt_current = RT_CURRENT; 00274 TEST_BUF(rt_current, bits_test); 00275 TEST_FUN(rt_current) = testfun; 00276 TEST_MASK(rt_current) = testmasks; 00277 rt_current->state |= RT_SCHED_SEMAPHORE; 00278 rem_ready_current(rt_current); 00279 enqueue_blocked(rt_current, &bits->queue, 1); 00280 rt_schedule(); 00281 mask = bits->mask; 00282 if (rt_current->blocked_on || bits->magic != RT_BITS_MAGIC) { 00283 rt_current->prio_passed_to = NOTHING; 00284 rt_global_restore_flags(flags); 00285 return BITS_ERR; 00286 } 00287 } else { 00288 mask = bits->mask; 00289 } 00290 exec_fun[exitfun](bits, exitmasks); 00291 rt_global_restore_flags(flags); 00292 if (resulting_mask) { 00293 if (space) { 00294 *resulting_mask = mask; 00295 } else { 00296 rt_copy_to_user(resulting_mask, &mask, sizeof(mask)); 00297 } 00298 } 00299 return 0; 00300 } 00301 00302 int _rt_bits_wait_if(BITS *bits, int testfun, unsigned long testmasks, int exitfun, unsigned long exitmasks, unsigned long *resulting_mask, int space) 00303 { 00304 unsigned long flags, mask; 00305 00306 if (bits->magic != RT_BITS_MAGIC) { 00307 return BITS_ERR; 00308 } 00309 00310 flags = rt_global_save_flags_and_cli(); 00311 mask = bits->mask; 00312 if (test_fun[testfun](bits, testmasks)) { 00313 exec_fun[exitfun](bits, exitmasks); 00314 rt_global_restore_flags(flags); 00315 return 1; 00316 } 00317 rt_global_restore_flags(flags); 00318 if (resulting_mask) { 00319 if (space) { 00320 *resulting_mask = mask; 00321 } else { 00322 rt_copy_to_user(resulting_mask, &mask, sizeof(mask)); 00323 } 00324 } 00325 return 0; 00326 } 00327 00328 int _rt_bits_wait_until(BITS *bits, int testfun, unsigned long testmasks, int exitfun, unsigned long exitmasks, RTIME time, unsigned long *resulting_mask, int space) 00329 { 00330 RT_TASK *rt_current; 00331 unsigned long flags, mask; 00332 00333 if (bits->magic != RT_BITS_MAGIC) { 00334 return BITS_ERR; 00335 } 00336 00337 flags = rt_global_save_flags_and_cli(); 00338 if (!test_fun[testfun](bits, testmasks)) { 00339 long bits_test[2]; 00340 rt_current = RT_CURRENT; 00341 TEST_BUF(rt_current, bits_test); 00342 TEST_FUN(rt_current) = testfun; 00343 TEST_MASK(rt_current) = testmasks; 00344 rt_current->blocked_on = &bits->queue; 00345 if ((rt_current->resume_time = time) > get_time()) { 00346 rt_current->state |= (RT_SCHED_SEMAPHORE | RT_SCHED_DELAYED); 00347 rem_ready_current(rt_current); 00348 enqueue_blocked(rt_current, &bits->queue, 1); 00349 enq_timed_task(rt_current); 00350 rt_schedule(); 00351 } else { 00352 rt_current->queue.prev = rt_current->queue.next = &rt_current->queue; 00353 } 00354 mask = bits->mask; 00355 if (bits->magic != RT_BITS_MAGIC) { 00356 rt_current->prio_passed_to = NOTHING; 00357 rt_global_restore_flags(flags); 00358 return BITS_ERR; 00359 } else if (rt_current->blocked_on) { 00360 dequeue_blocked(rt_current); 00361 rt_global_restore_flags(flags); 00362 return BITS_TIMOUT; 00363 } 00364 } else { 00365 mask = bits->mask; 00366 } 00367 exec_fun[exitfun](bits, exitmasks); 00368 rt_global_restore_flags(flags); 00369 if (resulting_mask) { 00370 if (space) { 00371 *resulting_mask = mask; 00372 } else { 00373 rt_copy_to_user(resulting_mask, &mask, sizeof(mask)); 00374 } 00375 } 00376 return 0; 00377 } 00378 00379 int _rt_bits_wait_timed(BITS *bits, int testfun, unsigned long testmasks, int exitfun, unsigned long exitmasks, RTIME delay, unsigned long *resulting_mask, int space) 00380 { 00381 return _rt_bits_wait_until(bits, testfun, testmasks, exitfun, exitmasks, get_time() + delay, resulting_mask, space); 00382 } 00383 00384 /* +++++++++++++++++++++++++++++ NAMED BITS +++++++++++++++++++++++++++++++++ */ 00385 00386 #include <rtai_registry.h> 00387 00388 BITS *rt_named_bits_init(const char *bits_name, unsigned long mask) 00389 { 00390 BITS *bits; 00391 unsigned long name; 00392 00393 if ((bits = rt_get_adr(name = nam2num(bits_name)))) { 00394 return bits; 00395 } 00396 if ((bits = rt_malloc(sizeof(SEM)))) { 00397 rt_bits_init(bits, mask); 00398 if (rt_register(name, bits, IS_BIT, 0)) { 00399 return bits; 00400 } 00401 rt_bits_delete(bits); 00402 } 00403 rt_free(bits); 00404 return (BITS *)0; 00405 } 00406 00407 int rt_named_bits_delete(BITS *bits) 00408 { 00409 if (!rt_bits_delete(bits)) { 00410 rt_free(bits); 00411 } 00412 return rt_drg_on_adr(bits); 00413 } 00414 00415 void *rt_bits_init_u(unsigned long name, unsigned long mask) 00416 { 00417 BITS *bits; 00418 if (rt_get_adr(name)) { 00419 return NULL; 00420 } 00421 if ((bits = rt_malloc(sizeof(BITS)))) { 00422 rt_bits_init(bits, mask); 00423 if (rt_register(name, bits, IS_BIT, current)) { 00424 return bits; 00425 } else { 00426 rt_free(bits); 00427 } 00428 } 00429 return NULL; 00430 } 00431 00432 int rt_bits_delete_u(BITS *bits) 00433 { 00434 if (rt_bits_delete(bits)) { 00435 return -EFAULT; 00436 } 00437 rt_free(bits); 00438 return rt_drg_on_adr(bits); 00439 } 00440 00441 /* ++++++++++++++++++++++++++++ BITS ENTRIES ++++++++++++++++++++++++++++++++ */ 00442 00443 struct rt_native_fun_entry rt_bits_entries[] = { 00444 { { 0, rt_bits_init_u }, BITS_INIT }, 00445 { { 0, rt_bits_delete_u }, BITS_DELETE }, 00446 { { 0, rt_named_bits_init }, NAMED_BITS_INIT }, 00447 { { 0, rt_named_bits_delete }, NAMED_BITS_DELETE }, 00448 { { 1, rt_get_bits }, BITS_GET }, 00449 { { 1, rt_bits_reset }, BITS_RESET }, 00450 { { 1, rt_bits_signal }, BITS_SIGNAL }, 00451 { { 1, _rt_bits_wait }, BITS_WAIT }, 00452 { { 1, _rt_bits_wait_if }, BITS_WAIT_IF }, 00453 { { 1, _rt_bits_wait_until }, BITS_WAIT_UNTIL }, 00454 { { 1, _rt_bits_wait_timed }, BITS_WAIT_TIMED }, 00455 { { 0, 0 }, 000 } 00456 }; 00457 00458 extern int set_rt_fun_entries(struct rt_native_fun_entry *entry); 00459 extern void reset_rt_fun_entries(struct rt_native_fun_entry *entry); 00460 00461 int __rtai_bits_init(void) 00462 { 00463 return set_rt_fun_entries(rt_bits_entries); 00464 } 00465 00466 void __rtai_bits_exit(void) 00467 { 00468 reset_rt_fun_entries(rt_bits_entries); 00469 } 00470 00471 #ifndef CONFIG_RTAI_BITS_BUILTIN 00472 module_init(__rtai_bits_init); 00473 module_exit(__rtai_bits_exit); 00474 #endif /* !CONFIG_RTAI_BITS_BUILTIN */ 00475 00476 #ifdef CONFIG_KBUILD 00477 EXPORT_SYMBOL(rt_bits_init); 00478 EXPORT_SYMBOL(rt_bits_delete); 00479 EXPORT_SYMBOL(rt_get_bits); 00480 EXPORT_SYMBOL(rt_bits_reset); 00481 EXPORT_SYMBOL(rt_bits_signal); 00482 EXPORT_SYMBOL(_rt_bits_wait); 00483 EXPORT_SYMBOL(_rt_bits_wait_if); 00484 EXPORT_SYMBOL(_rt_bits_wait_until); 00485 EXPORT_SYMBOL(_rt_bits_wait_timed); 00486 EXPORT_SYMBOL(rt_named_bits_init); 00487 EXPORT_SYMBOL(rt_named_bits_delete); 00488 EXPORT_SYMBOL(rt_bits_init_u); 00489 EXPORT_SYMBOL(rt_bits_delete_u); 00490 #endif /* CONFIG_KBUILD */

Generated on Thu Nov 20 11:49:50 2008 for RTAI API by doxygen 1.3.8