source: rtems/cpukit/libcsupport/src/printertask.c @ 1b322a6

Last change on this file since 1b322a6 was 1b322a6, checked in by Ryan Long <ryan.long@…>, on 02/19/21 at 22:06:38

printertask.c: Fix Unchecked return value (CID #1399710)

CID 1399710: Unchecked return value in printer_task().
CID 1472764: Unchecked return value in rtems_print_printer_task().

Closes #4258

  • Property mode set to 100644
File size: 5.0 KB
Line 
1/*
2 * Copyright (c) 2016 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Obere Lagerstr. 30
6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
12 * http://www.rtems.org/license/LICENSE.
13 */
14
15#ifdef HAVE_CONFIG_H
16#include "config.h"
17#endif
18
19#include <rtems/printer.h>
20
21#include <rtems.h>
22#include <rtems/seterr.h>
23
24#include <unistd.h>
25
26#define PRINT_TASK_WAKE_UP RTEMS_EVENT_0
27
28typedef struct {
29  rtems_chain_node node;
30
31  enum {
32    ACTION_WRITE,
33    ACTION_DRAIN
34  } action_kind;
35
36  union {
37    size_t   size;
38    rtems_id task;
39  } action_data;
40
41  char data[ RTEMS_ZERO_LENGTH_ARRAY ];
42} printer_task_buffer;
43
44static void printer_task_acquire(
45  rtems_printer_task_context   *ctx,
46  rtems_interrupt_lock_context *lock_context
47)
48{
49  rtems_interrupt_lock_acquire( &ctx->lock, lock_context );
50}
51
52static void printer_task_release(
53  rtems_printer_task_context   *ctx,
54  rtems_interrupt_lock_context *lock_context
55)
56{
57  rtems_interrupt_lock_release( &ctx->lock, lock_context );
58}
59
60static printer_task_buffer *printer_task_get_buffer(
61  rtems_printer_task_context *ctx,
62  rtems_chain_control        *chain
63)
64{
65  rtems_interrupt_lock_context  lock_context;
66  printer_task_buffer          *buffer;
67
68  printer_task_acquire( ctx, &lock_context );
69  buffer = (printer_task_buffer *) rtems_chain_get_unprotected( chain );
70  printer_task_release( ctx, &lock_context );
71
72  return buffer;
73}
74
75static void printer_task_append_buffer(
76  rtems_printer_task_context *ctx,
77  rtems_chain_control        *chain,
78  printer_task_buffer        *buffer
79)
80{
81  rtems_interrupt_lock_context lock_context;
82
83  printer_task_acquire( ctx, &lock_context );
84  rtems_chain_append_unprotected( chain, &buffer->node );
85  printer_task_release( ctx, &lock_context );
86}
87
88static int printer_task_printer( void *context, const char *fmt, va_list ap )
89{
90  rtems_printer_task_context *ctx;
91  printer_task_buffer        *buffer;
92  int                         n;
93
94  ctx = context;
95  buffer = printer_task_get_buffer( ctx, &ctx->free_buffers );
96
97  if ( buffer == NULL ) {
98    rtems_set_errno_and_return_minus_one( ENOMEM );
99  }
100
101  n = vsnprintf( &buffer->data[ 0 ], ctx->buffer_size, fmt, ap );
102
103  if ( n >= (int) ctx->buffer_size ) {
104    printer_task_append_buffer( ctx, &ctx->free_buffers, buffer );
105    rtems_set_errno_and_return_minus_one( EINVAL );
106  }
107
108  buffer->action_kind = ACTION_WRITE;
109  buffer->action_data.size = (size_t) n;
110  printer_task_append_buffer( ctx, &ctx->todo_buffers, buffer );
111  rtems_event_send( ctx->task, PRINT_TASK_WAKE_UP );
112
113  return n;
114}
115
116static void printer_task( rtems_task_argument arg )
117{
118  rtems_printer_task_context *ctx;
119  int                         fd;
120  int                         err;
121  rtems_status_code           sc;
122
123  ctx = (rtems_printer_task_context *) arg;
124  fd = ctx->fd;
125
126  while ( true ) {
127    rtems_event_set      unused;
128    printer_task_buffer *buffer;
129
130    rtems_event_receive(
131      PRINT_TASK_WAKE_UP,
132      RTEMS_EVENT_ALL | RTEMS_WAIT,
133      RTEMS_NO_TIMEOUT,
134      &unused
135    );
136
137    while (
138      ( buffer = printer_task_get_buffer( ctx, &ctx->todo_buffers ) ) != NULL
139    ) {
140      switch ( buffer->action_kind ) {
141        case ACTION_WRITE:
142          write( fd, &buffer->data[ 0 ], buffer->action_data.size );
143          printer_task_append_buffer( ctx, &ctx->free_buffers, buffer );
144          break;
145        case ACTION_DRAIN:
146          err = fsync(fd);
147          _Assert_Unused_variable_equals(err, 0);
148          sc = rtems_event_transient_send( buffer->action_data.task );
149          _Assert_Unused_variable_equals(sc, RTEMS_SUCCESSFUL);
150          break;
151      }
152    }
153  }
154}
155
156int rtems_print_printer_task(
157  rtems_printer              *printer,
158  rtems_printer_task_context *ctx
159)
160{
161  rtems_status_code sc;
162
163  if ( ctx->buffer_size < sizeof( printer_task_buffer ) ) {
164    return EINVAL;
165  }
166
167  sc = rtems_task_create(
168    rtems_build_name( 'P', 'R', 'N', 'T'),
169    ctx->task_priority,
170    ctx->task_stack_size,
171    RTEMS_DEFAULT_MODES,
172    RTEMS_DEFAULT_ATTRIBUTES,
173    &ctx->task
174  );
175
176  if ( sc != RTEMS_SUCCESSFUL ) {
177    return ENOMEM;
178  }
179
180  rtems_chain_initialize_empty( &ctx->todo_buffers );
181  rtems_chain_initialize(
182    &ctx->free_buffers,
183    ctx->buffer_table,
184    ctx->buffer_count,
185    ctx->buffer_size
186  );
187  ctx->buffer_size -= sizeof( printer_task_buffer );
188
189  printer->context = ctx;
190  printer->printer = printer_task_printer;
191
192  sc = rtems_task_start( ctx->task, printer_task, (rtems_task_argument) ctx );
193  _Assert_Unused_variable_equals(sc, RTEMS_SUCCESSFUL);
194
195  return 0;
196}
197
198void rtems_printer_task_drain( rtems_printer_task_context *ctx )
199{
200  printer_task_buffer buffer;
201
202  rtems_chain_initialize_node( &buffer.node );
203  buffer.action_kind = ACTION_DRAIN;
204  buffer.action_data.task = rtems_task_self();
205
206  printer_task_append_buffer( ctx, &ctx->todo_buffers, &buffer );
207  rtems_event_send( ctx->task, PRINT_TASK_WAKE_UP );
208  rtems_event_transient_receive( RTEMS_WAIT, RTEMS_NO_TIMEOUT );
209}
Note: See TracBrowser for help on using the repository browser.