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

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 */
                     45: static int kmsg_in_use;
                     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  */
                     49: static int kmsg_init_done = 0;
                     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);
                     58:   kmsg_in_use = 0;
                     59:   simple_lock_init (&kmsg_lock);
                     60: }
                     61: 
                     62: /* Kernel Message Open Handler */
                     63: io_return_t
                     64: kmsgopen (dev_t dev, int flag, io_req_t ior)
                     65: {
                     66:   simple_lock (&kmsg_lock);
                     67:   if (kmsg_in_use)
                     68:     {
                     69:       simple_unlock (&kmsg_lock);
                     70:       return D_ALREADY_OPEN;
                     71:     }
                     72:   
                     73:   kmsg_in_use = 1;
                     74: 
                     75:   simple_unlock (&kmsg_lock);
                     76:   return D_SUCCESS;
                     77: }
                     78: 
                     79: /* Kernel Message Close Handler */
                     80: io_return_t
                     81: kmsgclose (dev_t dev, int flag)
                     82: {
                     83:   simple_lock (&kmsg_lock);
                     84:   kmsg_in_use = 0;
                     85:   
                     86:   simple_unlock (&kmsg_lock);
                     87:   return D_SUCCESS;
                     88: }
                     89: 
                     90: static boolean_t kmsg_read_done (io_req_t ior);
                     91: 
                     92: /* Kernel Message Read Handler */
                     93: io_return_t
                     94: kmsgread (dev_t dev, io_req_t ior)
                     95: {
                     96:   int err;
                     97:   int amt, len;
                     98:   
                     99:   err = device_read_alloc (ior, ior->io_count);
                    100:   if (err != KERN_SUCCESS)
                    101:     return err;
                    102: 
                    103:   simple_lock (&kmsg_lock);
                    104:   if (kmsg_read_offset == kmsg_write_offset)
                    105:     {
                    106:       /* The queue is empty.  */
                    107:       if (ior->io_mode & D_NOWAIT)
                    108:        {
                    109:          simple_unlock (&kmsg_lock);
                    110:          return D_WOULD_BLOCK;
                    111:        }
                    112: 
                    113:       ior->io_done = kmsg_read_done;
1.1.1.2 ! root      114:       enqueue_tail (&kmsg_read_queue, (queue_entry_t) ior);
1.1       root      115:       simple_unlock (&kmsg_lock);
                    116:       return D_IO_QUEUED;
                    117:     }
                    118: 
                    119:   len = kmsg_write_offset - kmsg_read_offset;
                    120:   if (len < 0)
                    121:     len += KMSGBUFSIZE;
                    122: 
                    123:   amt = ior->io_count;
                    124:   if (amt > len)
                    125:     amt = len;
                    126:   
                    127:   if (kmsg_read_offset + amt <= KMSGBUFSIZE)
                    128:     {
                    129:       memcpy (ior->io_data, kmsg_buffer + kmsg_read_offset, amt);
                    130:     }
                    131:   else
                    132:     {
                    133:       int cnt;
                    134: 
                    135:       cnt = KMSGBUFSIZE - kmsg_read_offset;
                    136:       memcpy (ior->io_data, kmsg_buffer + kmsg_read_offset, cnt);
                    137:       memcpy (ior->io_data + cnt, kmsg_buffer, amt - cnt);
                    138:     }
                    139: 
                    140:   kmsg_read_offset += amt;
                    141:   if (kmsg_read_offset >= KMSGBUFSIZE)
                    142:     kmsg_read_offset -= KMSGBUFSIZE;
                    143:   
                    144:   ior->io_residual = ior->io_count - amt;
                    145:   
                    146:   simple_unlock (&kmsg_lock);
                    147:   return D_SUCCESS;
                    148: }
                    149: 
                    150: static boolean_t
                    151: kmsg_read_done (io_req_t ior)
                    152: {
                    153:   int amt, len;
                    154: 
                    155:   simple_lock (&kmsg_lock);
                    156:   if (kmsg_read_offset == kmsg_write_offset)
                    157:     {
                    158:       /* The queue is empty.  */
                    159:       ior->io_done = kmsg_read_done;
1.1.1.2 ! root      160:       enqueue_tail (&kmsg_read_queue, (queue_entry_t) ior);
1.1       root      161:       simple_unlock (&kmsg_lock);
                    162:       return FALSE;
                    163:     }
                    164: 
                    165:   len = kmsg_write_offset - kmsg_read_offset;
                    166:   if (len < 0)
                    167:     len += KMSGBUFSIZE;
                    168: 
                    169:   amt = ior->io_count;
                    170:   if (amt > len)
                    171:     amt = len;
                    172:   
                    173:   if (kmsg_read_offset + amt <= KMSGBUFSIZE)
                    174:     {
                    175:       memcpy (ior->io_data, kmsg_buffer + kmsg_read_offset, amt);
                    176:     }
                    177:   else
                    178:     {
                    179:       int cnt;
                    180: 
                    181:       cnt = KMSGBUFSIZE - kmsg_read_offset;
                    182:       memcpy (ior->io_data, kmsg_buffer + kmsg_read_offset, cnt);
                    183:       memcpy (ior->io_data + cnt, kmsg_buffer, amt - cnt);
                    184:     }
                    185: 
                    186:   kmsg_read_offset += amt;
                    187:   if (kmsg_read_offset >= KMSGBUFSIZE)
                    188:     kmsg_read_offset -= KMSGBUFSIZE;
                    189:   
                    190:   ior->io_residual = ior->io_count - amt;
                    191: 
                    192:   simple_unlock (&kmsg_lock);
                    193:   ds_read_done (ior);
                    194:   
                    195:   return TRUE;
                    196: }
                    197: 
                    198: io_return_t
                    199: kmsggetstat (dev_t dev, int flavor, int *data, unsigned int *count)
                    200: {
                    201:   switch (flavor)
                    202:     {
                    203:     case DEV_GET_SIZE:
                    204:       data[DEV_GET_SIZE_DEVICE_SIZE] = 0;
                    205:       data[DEV_GET_SIZE_RECORD_SIZE] = 1;
                    206:       *count = DEV_GET_SIZE_COUNT;
                    207:       break;
                    208: 
                    209:     default:
                    210:       return D_INVALID_OPERATION;
                    211:     }
                    212: 
                    213:   return D_SUCCESS;
                    214: }
                    215: 
                    216: /* Write to Kernel Message Buffer */
                    217: void
                    218: kmsg_putchar (int c)
                    219: {
                    220:   io_req_t ior;
                    221:   int offset;
                    222: 
                    223:   /* XXX: cninit is not called before cnputc is used. So call kmsginit
                    224:      here if not initialized yet.  */
                    225:   if (!kmsg_init_done)
                    226:     {
                    227:       kmsginit ();
                    228:       kmsg_init_done = 1;
                    229:     }
                    230:   
                    231:   simple_lock (&kmsg_lock);
                    232:   offset = kmsg_write_offset + 1;
                    233:   if (offset == KMSGBUFSIZE)
                    234:     offset = 0;
                    235: 
                    236:   if (offset == kmsg_read_offset)
                    237:     {
                    238:       /* Discard C.  */
                    239:       simple_unlock (&kmsg_lock);
                    240:       return;
                    241:     }
                    242: 
                    243:   kmsg_buffer[kmsg_write_offset++] = c;
                    244:   if (kmsg_write_offset == KMSGBUFSIZE)
                    245:     kmsg_write_offset = 0;
                    246: 
                    247:   while ((ior = (io_req_t) dequeue_head (&kmsg_read_queue)) != NULL)
                    248:     iodone (ior);
                    249: 
                    250:   simple_unlock (&kmsg_lock);
                    251: }

unix.superglobalmegacorp.com

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