Warning, cross-references for /kernel/util/circular.c need to be fixed.
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #include "arch/i386.h"
0019 #include "sched/sched.h"
0020 #include "util/circular.h"
0021
0022 static inline void
0023 circular_lock (circular *c)
0024 {
0025 spinlock_lock (&c->lock);
0026 }
0027
0028 static inline void
0029 circular_unlock (circular *c)
0030 {
0031 spinlock_unlock (&c->lock);
0032 }
0033
0034
0035
0036
0037 static sint32
0038 generic_circular_insert (circular *c, void *elt, uint32 flags)
0039 {
0040 sint32 ret;
0041
0042 circular_lock (c);
0043
0044 while (c->cur_count == c->num_elts) {
0045 if (flags & CIRCULAR_FLAG_NOWAIT) {
0046 ret = -1;
0047 goto finish;
0048 } else {
0049
0050 queue_append (&c->ins_waitq, str ());
0051 circular_unlock (c);
0052 schedule ();
0053 circular_lock (c);
0054 }
0055 }
0056
0057
0058
0059 memcpy (c->insert_ptr, elt, c->elt_size);
0060 c->insert_ptr += c->elt_size;
0061 if (c->insert_ptr >= c->buffer_end)
0062 c->insert_ptr = c->buffer;
0063 ret = ++c->cur_count;
0064 wakeup_queue (&c->rem_waitq);
0065
0066 finish:
0067 circular_unlock (c);
0068 return ret;
0069 }
0070
0071
0072
0073
0074 static sint32
0075 generic_circular_remove (circular *c, void *out_elt, uint32 flags)
0076 {
0077 sint32 ret;
0078
0079 circular_lock (c);
0080
0081 while (c->cur_count == 0) {
0082 if (flags & CIRCULAR_FLAG_NOWAIT) {
0083 ret = -1;
0084 goto finish;
0085 } else {
0086
0087 queue_append (&c->rem_waitq, str ());
0088 circular_unlock (c);
0089 schedule ();
0090 circular_lock (c);
0091 }
0092 }
0093
0094
0095
0096 memcpy (out_elt, c->remove_ptr, c->elt_size);
0097 c->remove_ptr += c->elt_size;
0098 if (c->remove_ptr >= c->buffer_end)
0099 c->remove_ptr = c->buffer;
0100 ret = --c->cur_count;
0101 wakeup_queue (&c->ins_waitq);
0102
0103 finish:
0104 circular_unlock (c);
0105 return ret;
0106 }
0107
0108
0109
0110 void
0111 circular_init (circular *c, void *buffer, sint32 num_elts, sint32 elt_size)
0112 {
0113 c->buffer = buffer;
0114 c->insert_ptr = buffer;
0115 c->remove_ptr = buffer;
0116 c->buffer_end = buffer + num_elts * elt_size;
0117 c->num_elts = num_elts;
0118 c->elt_size = elt_size;
0119 c->cur_count = 0;
0120
0121 c->insert = generic_circular_insert;
0122 c->remove = generic_circular_remove;
0123 spinlock_init (&c->lock);
0124 c->ins_waitq = 0;
0125 c->rem_waitq = 0;
0126 }
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137