source: rtems/cpukit/posix/src/shmopen.c @ 21275b58

5
Last change on this file since 21275b58 was 21275b58, checked in by Sebastian Huber <sebastian.huber@…>, on 11/22/18 at 18:14:51

score: Static Objects_Information initialization

Statically allocate the objects information together with the initial
set of objects either via <rtems/confdefs.h>. Provide default object
informations with zero objects via librtemscpu.a. This greatly
simplifies the workspace size estimate. RTEMS applications which do not
use the unlimited objects option are easier to debug since all objects
reside now in statically allocated objects of the right types.

Close #3621.

  • Property mode set to 100644
File size: 7.4 KB
Line 
1/**
2 * @file
3 */
4
5/*
6 * Copyright (c) 2016 Gedare Bloom.
7 *
8 * The license and distribution terms for this file may be
9 * found in the file LICENSE in this distribution or at
10 * http://www.rtems.org/license/LICENSE.
11 */
12
13#if HAVE_CONFIG_H
14#include "config.h"
15#endif
16
17#include <sys/mman.h>
18#include <errno.h>
19#include <unistd.h>
20#include <fcntl.h>
21#include <sys/stat.h>
22
23#include <rtems/libio_.h>
24#include <rtems/seterr.h>
25
26#include <rtems/posix/shmimpl.h>
27#include <rtems/score/wkspace.h>
28#include <rtems/sysinit.h>
29
30static const rtems_filesystem_file_handlers_r shm_handlers;
31
32static int shm_fstat(
33  const rtems_filesystem_location_info_t *loc,
34  struct stat *buf
35)
36{
37  POSIX_Shm_Control *shm = loc_to_shm( loc );
38
39  if ( shm == NULL )
40    rtems_set_errno_and_return_minus_one( EIO );
41
42  /* mandatory for shm objects */
43  buf->st_uid = shm->uid;
44  buf->st_gid = shm->gid;
45  buf->st_size = shm->shm_object.size;
46  buf->st_mode = shm->mode;
47
48  /* optional for shm objects */
49  buf->st_atime = shm->atime;
50  buf->st_mtime = shm->mtime;
51  buf->st_ctime = shm->ctime;
52
53  return 0;
54}
55
56/* read() is unspecified for shared memory objects */
57static ssize_t shm_read( rtems_libio_t *iop, void *buffer, size_t count )
58{
59  ssize_t bytes_read;
60  POSIX_Shm_Control *shm = iop_to_shm( iop );
61
62  _Objects_Allocator_lock();
63  bytes_read = (*shm->shm_object.ops->object_read)(
64      &shm->shm_object,
65      buffer,
66      count
67  );
68  _POSIX_Shm_Update_atime( shm );
69
70  _Objects_Allocator_unlock();
71  return bytes_read;
72}
73
74static int shm_ftruncate( rtems_libio_t *iop, off_t length )
75{
76  int err;
77  POSIX_Shm_Control *shm = iop_to_shm( iop );
78
79  _Objects_Allocator_lock();
80
81  err = (*shm->shm_object.ops->object_resize)( &shm->shm_object, length );
82
83  if ( err != 0 ) {
84    _Objects_Allocator_unlock();
85    rtems_set_errno_and_return_minus_one( err );
86  }
87
88  _POSIX_Shm_Update_mtime_ctime( shm );
89
90  _Objects_Allocator_unlock();
91  return 0;
92}
93
94static int shm_close( rtems_libio_t *iop )
95{
96  POSIX_Shm_Control *shm = iop_to_shm( iop );
97  int err;
98
99  err = 0;
100
101  POSIX_Shm_Attempt_delete(shm);
102  iop->pathinfo.node_access = NULL;
103
104  if ( err != 0 ) {
105    rtems_set_errno_and_return_minus_one( err );
106  }
107  return 0;
108}
109
110static int shm_mmap(
111  rtems_libio_t *iop,
112  void** addr,
113  size_t len,
114  int prot,
115  off_t off
116)
117{
118  POSIX_Shm_Control *shm = iop_to_shm( iop );
119
120  _Objects_Allocator_lock();
121
122  *addr = (*shm->shm_object.ops->object_mmap)( &shm->shm_object, len, prot, off);
123  if ( *addr != NULL ) {
124    /* Keep a reference in the shared memory to prevent its removal. */
125    ++shm->reference_count;
126
127    /* Update atime */
128    _POSIX_Shm_Update_atime(shm);
129  } else {
130    _Objects_Allocator_unlock();
131    rtems_set_errno_and_return_minus_one( ENOMEM );
132  }
133
134  _Objects_Allocator_unlock();
135
136  return 0;
137}
138
139static inline POSIX_Shm_Control *shm_allocate(
140  const char *name_arg,
141  size_t name_len,
142  int oflag,
143  mode_t mode,
144  int *error
145)
146{
147  POSIX_Shm_Control *shm;
148  char *name;
149  struct timeval tv;
150
151  /* Reject any name without a leading slash. */
152  if ( name_arg[0] != '/' ) {
153    *error = EINVAL;
154    return NULL;
155  }
156
157  /* Only create the object if requested. */
158  if ( ( oflag & O_CREAT ) != O_CREAT ) {
159    *error = ENOENT;
160    return NULL;
161  }
162
163  name = _Workspace_String_duplicate( name_arg, name_len );
164  if ( name == NULL ) {
165    *error = ENOSPC;
166    return NULL;
167  }
168
169  shm = _POSIX_Shm_Allocate_unprotected();
170  if ( shm == NULL ) {
171    _Workspace_Free( name );
172    *error = ENFILE;
173    return NULL;
174  }
175
176  gettimeofday( &tv, 0 );
177
178  shm->reference_count = 1;
179  shm->shm_object.handle = NULL;
180  shm->shm_object.size = 0;
181  shm->shm_object.ops = &_POSIX_Shm_Object_operations;
182  shm->mode = mode & ~rtems_filesystem_umask;
183  shm->oflag = oflag;
184  shm->uid = geteuid();
185  shm->gid = getegid();
186  shm->atime = (time_t) tv.tv_sec;
187  shm->mtime = (time_t) tv.tv_sec;
188  shm->ctime = (time_t) tv.tv_sec;
189
190  _Objects_Open_string( &_POSIX_Shm_Information, &shm->Object, name );
191
192  return shm;
193}
194
195static inline bool shm_access_ok( POSIX_Shm_Control *shm, int oflag )
196{
197  int flags;
198  if ( oflag & O_RDONLY ) {
199    flags = RTEMS_FS_PERMS_READ;
200  } else {
201    flags = RTEMS_FS_PERMS_WRITE;
202  }
203  return rtems_filesystem_check_access( flags, shm->mode, shm->uid, shm->gid );
204}
205
206static inline int shm_check_oflag( int oflag )
207{
208  if ( ( oflag & O_ACCMODE ) != O_RDONLY && ( oflag & O_ACCMODE ) != O_RDWR ) {
209    rtems_set_errno_and_return_minus_one( EACCES );
210  }
211
212  if ( ( oflag & ~( O_RDONLY | O_RDWR | O_CREAT | O_EXCL | O_TRUNC ) ) != 0 ) {
213    rtems_set_errno_and_return_minus_one( EACCES );
214  }
215
216  if ( ( oflag & O_TRUNC ) != 0 && ( oflag & O_ACCMODE ) != O_RDWR ) {
217    rtems_set_errno_and_return_minus_one( EACCES );
218  }
219  return 0;
220}
221
222int shm_open( const char *name, int oflag, mode_t mode )
223{
224  int err = 0;
225  int fd;
226  rtems_libio_t *iop;
227  POSIX_Shm_Control *shm;
228  size_t len;
229  Objects_Get_by_name_error obj_err;
230  unsigned int flags;
231
232  if ( shm_check_oflag( oflag ) != 0 ) {
233    return -1;
234  }
235
236  iop = rtems_libio_allocate();
237  if ( iop == NULL ) {
238    rtems_set_errno_and_return_minus_one( EMFILE );
239  }
240
241  _Objects_Allocator_lock();
242  shm = _POSIX_Shm_Get_by_name( name, &len, &obj_err );
243
244  if ( shm == NULL ) {
245    switch ( obj_err ) {
246      case OBJECTS_GET_BY_NAME_INVALID_NAME:
247        err = EINVAL;
248        break;
249
250      case OBJECTS_GET_BY_NAME_NAME_TOO_LONG:
251        err = ENAMETOOLONG;
252        break;
253
254      case OBJECTS_GET_BY_NAME_NO_OBJECT:
255      default:
256        shm = shm_allocate(name, len, oflag, mode, &err);
257        break;
258    }
259  } else { /* shm exists */
260    if ( ( oflag & ( O_EXCL | O_CREAT ) ) == ( O_EXCL | O_CREAT ) ) {
261      /* Request to create failed. */
262      err = EEXIST;
263    } else if ( !shm_access_ok( shm, oflag ) ) {
264      err = EACCES;
265    } else {
266      ++shm->reference_count;
267    }
268  }
269  _Objects_Allocator_unlock();
270  if ( err != 0 ) {
271    rtems_libio_free( iop );
272    rtems_set_errno_and_return_minus_one( err );
273  }
274
275  if ( oflag & O_TRUNC ) {
276    err = shm_ftruncate( iop, 0 );
277    (void) err; /* ignore truncate error */
278  }
279
280  fd = rtems_libio_iop_to_descriptor( iop );
281  iop->data0 = fd;
282  iop->data1 = shm;
283  iop->pathinfo.node_access = shm;
284  iop->pathinfo.handlers = &shm_handlers;
285  iop->pathinfo.mt_entry = &rtems_filesystem_null_mt_entry;
286  rtems_filesystem_location_add_to_mt_entry( &iop->pathinfo );
287
288  flags = LIBIO_FLAGS_CLOSE_ON_EXEC;
289  if ( oflag & O_RDONLY ) {
290    flags |= LIBIO_FLAGS_READ;
291  } else {
292    flags |= LIBIO_FLAGS_READ_WRITE;
293  }
294
295  rtems_libio_iop_flags_initialize( iop, flags );
296
297  return fd;
298}
299
300static const rtems_filesystem_file_handlers_r shm_handlers = {
301  .open_h = rtems_filesystem_default_open,
302  .close_h = shm_close,
303  .read_h = shm_read,
304  .write_h = rtems_filesystem_default_write,
305  .ioctl_h = rtems_filesystem_default_ioctl,
306  .lseek_h = rtems_filesystem_default_lseek,
307  .fstat_h = shm_fstat,
308  .ftruncate_h = shm_ftruncate,
309  .fsync_h = rtems_filesystem_default_fsync_or_fdatasync,
310  .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync,
311  .fcntl_h = rtems_filesystem_default_fcntl,
312  .kqfilter_h = rtems_filesystem_default_kqfilter,
313  .mmap_h = shm_mmap,
314  .poll_h = rtems_filesystem_default_poll,
315  .readv_h = rtems_filesystem_default_readv,
316  .writev_h = rtems_filesystem_default_writev
317};
318
319static void _POSIX_Shm_Manager_initialization( void )
320{
321  _Objects_Initialize_information( &_POSIX_Shm_Information );
322}
323
324RTEMS_SYSINIT_ITEM(
325  _POSIX_Shm_Manager_initialization,
326  RTEMS_SYSINIT_POSIX_SHM,
327  RTEMS_SYSINIT_ORDER_MIDDLE
328);
Note: See TracBrowser for help on using the repository browser.