source: rtems/cpukit/libcsupport/src/consolesimpletask.c

Last change on this file was bcef89f2, checked in by Sebastian Huber <sebastian.huber@…>, on 05/19/23 at 06:18:25

Update company name

The embedded brains GmbH & Co. KG is the legal successor of embedded
brains GmbH.

  • Property mode set to 100644
File size: 6.9 KB
Line 
1/* SPDX-License-Identifier: BSD-2-Clause */
2
3/*
4 * Copyright (C) 2018, 2020 embedded brains GmbH & Co. KG
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#ifdef HAVE_CONFIG_H
29#include "config.h"
30#endif
31
32#include <rtems/console.h>
33#include <rtems/bspIo.h>
34#include <rtems/imfs.h>
35#include <rtems/thread.h>
36
37#include "consolesimple.h"
38
39#define CONSOLE_SIMPLE_TASK_BUFFER_SIZE 2048
40
41#define CONSOLE_SIMPLE_TASK_MAX_JUNK_SIZE 80
42
43typedef struct {
44  IMFS_jnode_t Node;
45  RTEMS_INTERRUPT_LOCK_MEMBER( buf_lock )
46  rtems_mutex output_mutex;
47  rtems_id task;
48  size_t head;
49  size_t tail;
50  char buf[ CONSOLE_SIMPLE_TASK_BUFFER_SIZE ];
51} Console_simple_task_Control;
52
53static Console_simple_task_Control _Console_simple_task_Instance;
54
55static size_t _Console_simple_task_Capacity(
56  const Console_simple_task_Control *cons
57)
58{
59  return ( cons->tail - cons->head - 1 ) % CONSOLE_SIMPLE_TASK_BUFFER_SIZE;
60}
61
62static size_t _Console_simple_task_Available(
63  const Console_simple_task_Control *cons
64)
65{
66  return ( cons->head - cons->tail ) % CONSOLE_SIMPLE_TASK_BUFFER_SIZE;
67}
68
69static Console_simple_task_Control *_Console_simple_task_Iop_to_control(
70  const rtems_libio_t *iop
71)
72{
73  return (Console_simple_task_Control *) IMFS_iop_to_node( iop );
74}
75
76static ssize_t _Console_simple_task_Write(
77  rtems_libio_t *iop,
78  const void    *buffer,
79  size_t         count
80)
81{
82  Console_simple_task_Control *cons;
83  const char                  *buf;
84  size_t                       todo;
85
86  cons = _Console_simple_task_Iop_to_control( iop );
87  buf = buffer;
88  todo = count;
89
90  while ( todo > 0 ) {
91    rtems_interrupt_lock_context lock_context;
92    size_t                       junk;
93    size_t                       head;
94    size_t                       i;
95
96    rtems_interrupt_lock_acquire( &cons->buf_lock, &lock_context );
97
98    junk = _Console_simple_task_Capacity( cons );
99
100    if ( junk > todo ) {
101      junk = todo;
102    }
103
104    if ( junk > CONSOLE_SIMPLE_TASK_MAX_JUNK_SIZE ) {
105      junk = CONSOLE_SIMPLE_TASK_MAX_JUNK_SIZE;
106    }
107
108    head = cons->head;
109
110    for ( i = 0; i < junk; ++i ) {
111      cons->buf[ head ] = *buf;
112      head = ( head + 1 ) % CONSOLE_SIMPLE_TASK_BUFFER_SIZE;
113      --todo;
114      ++buf;
115    }
116
117    cons->head = head;
118
119    rtems_interrupt_lock_release( &cons->buf_lock, &lock_context );
120
121    if ( junk == 0 ) {
122      break;
123    }
124  }
125
126  rtems_event_system_send( cons->task, RTEMS_EVENT_SYSTEM_SERVER );
127
128  return (ssize_t) ( count - todo );
129}
130
131static void _Console_simple_task_Put_chars( Console_simple_task_Control *cons )
132{
133  rtems_interrupt_lock_context lock_context;
134  size_t                       available;
135  size_t                       tail;
136  size_t                       i;
137
138  rtems_mutex_lock( &cons->output_mutex );
139
140  rtems_interrupt_lock_acquire( &cons->buf_lock, &lock_context );
141
142  available = _Console_simple_task_Available( cons );
143  tail = cons->tail;
144
145  rtems_interrupt_lock_release( &cons->buf_lock, &lock_context );
146
147  for ( i = 0; i < available; ++i) {
148    rtems_putc( cons->buf[ tail ] );
149    tail = ( tail + 1 ) % CONSOLE_SIMPLE_TASK_BUFFER_SIZE;
150  }
151
152  rtems_interrupt_lock_acquire( &cons->buf_lock, &lock_context );
153
154  cons->tail = tail;
155
156  rtems_interrupt_lock_release( &cons->buf_lock, &lock_context );
157
158  rtems_mutex_unlock( &cons->output_mutex );
159}
160
161static int _Console_simple_task_Fsync( rtems_libio_t *iop )
162{
163  Console_simple_task_Control *cons;
164
165  cons = _Console_simple_task_Iop_to_control( iop );
166  _Console_simple_task_Put_chars( cons );
167
168  return 0;
169}
170
171static const rtems_filesystem_file_handlers_r _Console_simple_task_Handlers = {
172  .open_h = rtems_filesystem_default_open,
173  .close_h = rtems_filesystem_default_close,
174  .read_h = _Console_simple_Read,
175  .write_h = _Console_simple_task_Write,
176  .ioctl_h = rtems_filesystem_default_ioctl,
177  .lseek_h = rtems_filesystem_default_lseek,
178  .fstat_h = IMFS_stat,
179  .ftruncate_h = rtems_filesystem_default_ftruncate,
180  .fsync_h = _Console_simple_task_Fsync,
181  .fdatasync_h = _Console_simple_task_Fsync,
182  .fcntl_h = rtems_filesystem_default_fcntl,
183  .readv_h = rtems_filesystem_default_readv,
184  .writev_h = rtems_filesystem_default_writev,
185  .mmap_h = rtems_filesystem_default_mmap
186};
187
188static const IMFS_node_control
189_Console_simple_task_Node_control = IMFS_NODE_CONTROL_INITIALIZER(
190  &_Console_simple_task_Handlers,
191  IMFS_node_initialize_default,
192  IMFS_do_nothing_destroy
193);
194
195static void _Console_simple_task_Task( rtems_task_argument arg )
196{
197  Console_simple_task_Control *cons;
198
199  cons = (Console_simple_task_Control *) arg;
200
201  while ( true ) {
202    rtems_event_set events;
203
204    rtems_event_system_receive(
205      RTEMS_EVENT_SYSTEM_SERVER,
206      RTEMS_WAIT | RTEMS_EVENT_ALL,
207      RTEMS_NO_TIMEOUT,
208      &events
209    );
210
211    _Console_simple_task_Put_chars( cons );
212  }
213}
214
215static const char _Console_simple_task_Name[] = "console";
216
217void _Console_simple_task_Initialize( void )
218{
219  Console_simple_task_Control *cons;
220  rtems_status_code status;
221
222  cons = &_Console_simple_task_Instance;
223
224  IMFS_node_preinitialize(
225    &cons->Node,
226    &_Console_simple_task_Node_control,
227    _Console_simple_task_Name,
228    sizeof( _Console_simple_task_Name ) - 1,
229    S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO
230  );
231
232  rtems_interrupt_lock_initialize( &cons->buf_lock, "Console" );
233  rtems_mutex_init( &cons->output_mutex, "Console" );
234
235  IMFS_add_node( "/dev", &cons->Node, NULL );
236
237  status = rtems_task_create(
238    rtems_build_name('C', 'O', 'N', 'S'),
239    RTEMS_MAXIMUM_PRIORITY - 1,
240    RTEMS_MINIMUM_STACK_SIZE,
241    RTEMS_DEFAULT_ATTRIBUTES,
242    RTEMS_DEFAULT_MODES,
243    &cons->task
244  );
245  _Assert_Unused_variable_equals(status, RTEMS_SUCCESSFUL);
246
247  status = rtems_task_start(
248    cons->task,
249    _Console_simple_task_Task,
250    (rtems_task_argument) cons
251  );
252  _Assert_Unused_variable_equals(status, RTEMS_SUCCESSFUL);
253}
Note: See TracBrowser for help on using the repository browser.