source: trunk/kernel/kern/mwmr.c @ 305

Last change on this file since 305 was 1, checked in by alain, 8 years ago

First import

File size: 3.7 KB
Line 
1/*
2 * kern/mwmr.c - a basic FIFO buffer
3 *
4 * Copyright (c) 2007,2008,2009,2010,2011,2012 Ghassan Almaless
5 * Copyright (c) 2011,2012 UPMC Sorbonne Universites
6 *
7 * This file is part of ALMOS-kernel.
8 *
9 * ALMOS-kernel is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; version 2.0 of the License.
12 *
13 * ALMOS-kernel is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with ALMOS-kernel; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23#include <errno.h>
24#include <mwmr.h>
25#include <kmem.h>
26#include <thread.h>
27#include <spinlock.h>
28
29struct fifomwmr_s
30{
31        spinlock_t lock;
32        uint_t isAtomic;
33        uint_t status;
34        uint_t read_ptr;
35        uint_t write_ptr;
36        char *data;
37        uint_t item;
38        uint_t length;
39};
40
41struct fifomwmr_s* mwmr_init(int item, int length, int isAtomic)
42{
43        kmem_req_t req;
44        struct fifomwmr_s *fifo;
45        char *data;
46
47        req.type  = KMEM_GENERIC;
48        req.size  = sizeof(*fifo);
49        req.flags = AF_BOOT | AF_ZERO;
50 
51        if((fifo = kmem_alloc(&req)) == NULL)
52                return NULL;
53 
54        req.size = sizeof (unsigned int) * item * length;
55
56        if((data = kmem_alloc(&req)) == NULL)
57        {
58                printk(WARNING, "WARNING: mwmr_init: MEMORY SHORTAGE\n");
59                req.ptr = fifo;
60                kmem_free(&req);
61                return NULL;
62        }
63
64        spinlock_init(&fifo->lock, "MWMR");
65        fifo->isAtomic = isAtomic;
66        fifo->item     = item;
67        fifo->length   = length * item;
68        fifo->data     = data;
69 
70        return fifo;
71}
72
73int mwmr_read(struct fifomwmr_s *fifo, void *buffer, size_t size)
74{
75        register int rnum;                    // number of words to read
76        register char *src;
77        register int i, size1, size2;
78        register char *buff = (char *) buffer;
79
80        if (size == 0)
81                return 0;
82
83        if(fifo->isAtomic)
84                spinlock_lock(&fifo->lock);
85
86        rnum = (size > fifo->status) ? fifo->status : size;
87
88        if (rnum)
89        {
90                src = fifo->data + fifo->read_ptr;
91                if ((fifo->read_ptr + rnum) <= fifo->length)
92                        for (i = 0; i < rnum; i++)
93                                buff[i] = src[i];
94                else
95                {
96                        size1 = fifo->length - fifo->read_ptr;
97                        size2 = rnum - size1;
98
99                        for (i = 0; i < size1; i++)
100                                buff[i] = src[i];
101
102                        for (i = 0; i < size2; i++)
103                                buff[size1 + i] = *(fifo->data + i);
104                }
105
106                fifo->status  -= rnum;
107                fifo->read_ptr = (fifo->read_ptr + rnum) % fifo->length;
108        }
109
110        if(fifo->isAtomic)
111                spinlock_unlock(&fifo->lock);
112
113        return rnum;
114}
115
116int mwmr_write(struct fifomwmr_s *fifo, void *buffer, size_t size)
117{
118        register int free_space;
119        register int wnum;                    // number of words to write
120        register char *dest;
121        register int i, size1, size2;
122        register char *buff = (char *) buffer;
123
124        if (size == 0)
125                return 0;
126
127        if(fifo->isAtomic)
128                spinlock_lock (&fifo->lock);
129
130        free_space = fifo->length - fifo->status;
131        wnum       = (size > free_space) ? free_space : size;
132
133        if (wnum)
134        {
135                dest = (fifo->data + fifo->write_ptr);
136
137                if ((fifo->write_ptr + wnum) <= fifo->length)
138                        for (i = 0; i < wnum; i++)
139                                dest[i] = buff[i];
140                else
141                {
142                        size1 = fifo->length - fifo->write_ptr;
143                        size2 = wnum - size1;
144
145                        for (i = 0; i < size1; i++)
146                                dest[i] = buff[i];
147
148                        for (i = 0; i < size2; i++)
149                                *(fifo->data + i) = buff[size1 + i];
150                }
151
152                fifo->status += wnum;
153                fifo->write_ptr = (fifo->write_ptr + wnum) % fifo->length;
154        }
155
156        if(fifo->isAtomic)
157                spinlock_unlock(&fifo->lock);
158
159        return wnum;
160}
161
162void mwmr_destroy(struct fifomwmr_s *fifo)
163{
164        kmem_req_t req;
165 
166        if(fifo == NULL) return;
167
168        req.type = KMEM_GENERIC;
169        req.ptr  = fifo->data;
170        kmem_free(&req);
171 
172        req.ptr  = fifo;
173        kmem_free(&req);
174}
Note: See TracBrowser for help on using the repository browser.