Annotation of Gnu-Mach/device/kmsg.c, revision 1.1.1.3

1.1       root        1: /* GNU Mach Kernel Message Device.
1.1.1.2   root        2: 
                      3:    Copyright (C) 1998, 1999, 2007 Free Software Foundation, Inc.
                      4: 
1.1       root        5:    Written by OKUJI Yoshinori.
                      6: 
                      7: This is free software; you can redistribute it and/or modify
                      8: it under the terms of the GNU General Public License as published by
                      9: the Free Software Foundation; either version 2, or (at your option)
                     10: any later version.
                     11: 
                     12: This software is distributed in the hope that it will be useful,
                     13: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     15: GNU General Public License for more details.
                     16: 
                     17: You should have received a copy of the GNU General Public License
                     18: along with the software; see the file COPYING.  If not, write to
                     19: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
                     20: 
1.1.1.2   root       21: /* kmsg provides a stream interface.  */
1.1       root       22: 
                     23: #include <sys/types.h>
1.1.1.2   root       24: #include <string.h>
                     25: 
1.1       root       26: #include <device/conf.h>
1.1.1.2   root       27: #include <device/ds_routines.h>
1.1       root       28: #include <device/io_req.h>
                     29: #include <mach/boolean.h>
                     30: #include <kern/lock.h>
1.1.1.2   root       31: #include <device/kmsg.h>
1.1       root       32: 
                     33: 
                     34: #define KMSGBUFSIZE    (4096)  /* XXX */
                     35: 
                     36: /* Simple array for buffering messages */
                     37: static char kmsg_buffer[KMSGBUFSIZE];
                     38: /* Point to the offset to write */
                     39: static int kmsg_write_offset;
                     40: /* Point to the offset to read */
                     41: static int kmsg_read_offset;
                     42: /* I/O request queue for blocking read */
                     43: static queue_head_t kmsg_read_queue;
                     44: /* Used for exclusive access to the device */
1.1.1.3 ! root       45: static boolean_t kmsg_in_use;
1.1       root       46: /* Used for exclusive access to the routines */
1.1.1.2   root       47: decl_simple_lock_data (static, kmsg_lock);
1.1       root       48: /* If already initialized or not  */
1.1.1.3 ! root       49: static boolean_t kmsg_init_done = FALSE;
1.1       root       50: 
                     51: /* Kernel Message Initializer */
                     52: static void
                     53: kmsginit (void)
                     54: {
                     55:   kmsg_write_offset = 0;
                     56:   kmsg_read_offset = 0;
                     57:   queue_init (&kmsg_read_queue);
1.1.1.3 ! root       58:   kmsg_in_use = FALSE;
1.1       root       59:   simple_lock_init (&kmsg_lock);
                     60: }
                     61: 
                     62: /* Kernel Message Open Handler */
                     63: io_return_t
1.1.1.3 ! root       64: kmsgopen (dev_t dev, int flag, const io_req_t ior)
1.1       root       65: {
                     66:   simple_lock (&kmsg_lock);
                     67:   if (kmsg_in_use)
                     68:     {
                     69:       simple_unlock (&kmsg_lock);
                     70:       return D_ALREADY_OPEN;
                     71:     }
                     72:   
1.1.1.3 ! root       73:   kmsg_in_use = TRUE;
1.1       root       74: 
                     75:   simple_unlock (&kmsg_lock);
                     76:   return D_SUCCESS;
                     77: }
                     78: 
                     79: /* Kernel Message Close Handler */
1.1.1.3 ! root       80: void
1.1       root       81: kmsgclose (dev_t dev, int flag)
                     82: {
                     83:   simple_lock (&kmsg_lock);
1.1.1.3 ! root       84:   kmsg_in_use = FALSE;
1.1       root       85:   
                     86:   simple_unlock (&kmsg_lock);
                     87: }
                     88: 
                     89: static boolean_t kmsg_read_done (io_req_t ior);
                     90: 
                     91: /* Kernel Message Read Handler */
                     92: io_return_t
                     93: kmsgread (dev_t dev, io_req_t ior)
                     94: {
                     95:   int err;
                     96:   int amt, len;
                     97:   
                     98:   err = device_read_alloc (ior, ior->io_count);
                     99:   if (err != KERN_SUCCESS)
                    100:     return err;
                    101: 
                    102:   simple_lock (&kmsg_lock);
                    103:   if (kmsg_read_offset == kmsg_write_offset)
                    104:     {
                    105:       /* The queue is empty.  */
                    106:       if (ior->io_mode & D_NOWAIT)
                    107:        {
                    108:          simple_unlock (&kmsg_lock);
                    109:          return D_WOULD_BLOCK;
                    110:        }
                    111: 
                    112:       ior->io_done = kmsg_read_done;
1.1.1.2   root      113:       enqueue_tail (&kmsg_read_queue, (queue_entry_t) ior);
1.1       root      114:       simple_unlock (&kmsg_lock);
                    115:       return D_IO_QUEUED;
                    116:     }
                    117: 
                    118:   len = kmsg_write_offset - kmsg_read_offset;
                    119:   if (len < 0)
                    120:     len += KMSGBUFSIZE;
                    121: 
                    122:   amt = ior->io_count;
                    123:   if (amt > len)
                    124:     amt = len;
                    125:   
                    126:   if (kmsg_read_offset + amt <= KMSGBUFSIZE)
                    127:     {
                    128:       memcpy (ior->io_data, kmsg_buffer + kmsg_read_offset, amt);
                    129:     }
                    130:   else
                    131:     {
                    132:       int cnt;
                    133: 
                    134:       cnt = KMSGBUFSIZE - kmsg_read_offset;
                    135:       memcpy (ior->io_data, kmsg_buffer + kmsg_read_offset, cnt);
                    136:       memcpy (ior->io_data + cnt, kmsg_buffer, amt - cnt);
                    137:     }
                    138: 
                    139:   kmsg_read_offset += amt;
                    140:   if (kmsg_read_offset >= KMSGBUFSIZE)
                    141:     kmsg_read_offset -= KMSGBUFSIZE;
                    142:   
                    143:   ior->io_residual = ior->io_count - amt;
                    144:   
                    145:   simple_unlock (&kmsg_lock);
                    146:   return D_SUCCESS;
                    147: }
                    148: 
                    149: static boolean_t
                    150: kmsg_read_done (io_req_t ior)
                    151: {
                    152:   int amt, len;
                    153: 
                    154:   simple_lock (&kmsg_lock);
                    155:   if (kmsg_read_offset == kmsg_write_offset)
                    156:     {
                    157:       /* The queue is empty.  */
                    158:       ior->io_done = kmsg_read_done;
1.1.1.2   root      159:       enqueue_tail (&kmsg_read_queue, (queue_entry_t) ior);
1.1       root      160:       simple_unlock (&kmsg_lock);
                    161:       return FALSE;
                    162:     }
                    163: 
                    164:   len = kmsg_write_offset - kmsg_read_offset;
                    165:   if (len < 0)
                    166:     len += KMSGBUFSIZE;
                    167: 
                    168:   amt = ior->io_count;
                    169:   if (amt > len)
                    170:     amt = len;
                    171:   
                    172:   if (kmsg_read_offset + amt <= KMSGBUFSIZE)
                    173:     {
                    174:       memcpy (ior->io_data, kmsg_buffer + kmsg_read_offset, amt);
                    175:     }
                    176:   else
                    177:     {
                    178:       int cnt;
                    179: 
                    180:       cnt = KMSGBUFSIZE - kmsg_read_offset;
                    181:       memcpy (ior->io_data, kmsg_buffer + kmsg_read_offset, cnt);
                    182:       memcpy (ior->io_data + cnt, kmsg_buffer, amt - cnt);
                    183:     }
                    184: 
                    185:   kmsg_read_offset += amt;
                    186:   if (kmsg_read_offset >= KMSGBUFSIZE)
                    187:     kmsg_read_offset -= KMSGBUFSIZE;
                    188:   
                    189:   ior->io_residual = ior->io_count - amt;
                    190: 
                    191:   simple_unlock (&kmsg_lock);
                    192:   ds_read_done (ior);
                    193:   
                    194:   return TRUE;
                    195: }
                    196: 
                    197: io_return_t
                    198: kmsggetstat (dev_t dev, int flavor, int *data, unsigned int *count)
                    199: {
                    200:   switch (flavor)
                    201:     {
                    202:     case DEV_GET_SIZE:
                    203:       data[DEV_GET_SIZE_DEVICE_SIZE] = 0;
                    204:       data[DEV_GET_SIZE_RECORD_SIZE] = 1;
                    205:       *count = DEV_GET_SIZE_COUNT;
                    206:       break;
                    207: 
                    208:     default:
                    209:       return D_INVALID_OPERATION;
                    210:     }
                    211: 
                    212:   return D_SUCCESS;
                    213: }
                    214: 
                    215: /* Write to Kernel Message Buffer */
                    216: void
                    217: kmsg_putchar (int c)
                    218: {
                    219:   io_req_t ior;
                    220:   int offset;
                    221: 
                    222:   /* XXX: cninit is not called before cnputc is used. So call kmsginit
                    223:      here if not initialized yet.  */
                    224:   if (!kmsg_init_done)
                    225:     {
                    226:       kmsginit ();
1.1.1.3 ! root      227:       kmsg_init_done = TRUE;
1.1       root      228:     }
                    229:   
                    230:   simple_lock (&kmsg_lock);
                    231:   offset = kmsg_write_offset + 1;
                    232:   if (offset == KMSGBUFSIZE)
                    233:     offset = 0;
                    234: 
                    235:   if (offset == kmsg_read_offset)
                    236:     {
                    237:       /* Discard C.  */
                    238:       simple_unlock (&kmsg_lock);
                    239:       return;
                    240:     }
                    241: 
                    242:   kmsg_buffer[kmsg_write_offset++] = c;
                    243:   if (kmsg_write_offset == KMSGBUFSIZE)
                    244:     kmsg_write_offset = 0;
                    245: 
                    246:   while ((ior = (io_req_t) dequeue_head (&kmsg_read_queue)) != NULL)
                    247:     iodone (ior);
                    248: 
                    249:   simple_unlock (&kmsg_lock);
                    250: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.