source: asp3_tinet_ecnl_arm/trunk/ntshell/src/fdtable.c@ 387

Last change on this file since 387 was 387, checked in by coas-nagasima, 5 years ago

ファイルディスクリプタ処理を更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 11.7 KB
Line 
1/*
2 * TOPPERS ECHONET Lite Communication Middleware
3 *
4 * Copyright (C) 2017 Cores Co., Ltd. Japan
5 *
6 * 上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
7 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
8 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
9 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
10 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
11 * スコード中に含まれていること.
12 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
13 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
14 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
15 * の無保証規定を掲載すること.
16 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
17 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
18 * と.
19 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
20 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
21 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
22 * 報告すること.
23 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
24 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
25 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
26 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
27 * 免責すること.
28 *
29 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
30 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
31 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
32 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
33 * の責任を負わない.
34 *
35 * @(#) $Id$
36 */
37#include "shellif.h"
38#include <stdint.h>
39#include <kernel.h>
40#include <t_syslog.h>
41#include <t_stdlib.h>
42#include <sil.h>
43#include "syssvc/serial.h"
44#include "syssvc/syslog.h"
45#include "target_syssvc.h"
46#include "fdtable.h"
47#include "kernel_cfg.h"
48#include <string.h>
49#include "util/ntstdio.h"
50#include "hal/serial_api.h"
51
52#ifdef _DEBUG
53static const char THIS_FILE[] = __FILE__;
54#endif
55
56extern IO_TYPE IO_TYPE_STDIN;
57extern IO_TYPE IO_TYPE_STDOUT;
58extern IO_TYPE IO_TYPE_STDERR;
59
60static struct SHELL_FILE fd_table[8 * sizeof(FLGPTN)] = {
61 { STDIN_FILENO, &IO_TYPE_STDIN, 0 },
62 { STDOUT_FILENO, &IO_TYPE_STDOUT, 0 },
63 { STDERR_FILENO, &IO_TYPE_STDERR, 0 },
64};
65#define fd_table_count (sizeof(fd_table) / sizeof(fd_table[0]))
66
67struct SHELL_FILE *new_fp(IO_TYPE *type, int id, int writable)
68{
69 struct SHELL_FILE *fp = NULL;
70 ER ret;
71
72 ret = wai_sem(SEM_FILEDESC);
73 if (ret < 0) {
74 syslog(LOG_ERROR, "wai_sem => %d", ret);
75 }
76
77 for (int fd = 3; fd < fd_table_count; fd++) {
78 fp = &fd_table[fd];
79 if (fp->type != NULL)
80 continue;
81
82 memset(fp, 0, sizeof(struct SHELL_FILE));
83 fp->fd = fd;
84 fp->type = type;
85 fp->handle = id;
86 fp->writable = writable;
87 break;
88 }
89
90 ret = sig_sem(SEM_FILEDESC);
91 if (ret < 0) {
92 syslog(LOG_ERROR, "sig_sem => %d", ret);
93 }
94
95 if (fp != NULL) {
96 FLGPTN flgptn = 0;
97
98 FD_SET(fp->fd, (fd_set *)&flgptn);
99
100 ret = clr_flg(FLG_SELECT_WAIT, ~flgptn);
101 if (ret != E_OK) {
102 syslog(LOG_ERROR, "clr_flg => %d", ret);
103 }
104 }
105
106 return fp;
107}
108
109struct SHELL_FILE *id_to_fd(IO_TYPE *type, int id)
110{
111 struct SHELL_FILE *fp = NULL;
112 ER ret;
113
114 ret = wai_sem(SEM_FILEDESC);
115 if (ret < 0) {
116 syslog(LOG_ERROR, "wai_sem => %d", ret);
117 }
118
119 for (int fd = 3; fd < fd_table_count; fd++) {
120 fp = &fd_table[fd];
121 if ((fp->type == type) && (fp->handle == id))
122 break;
123 }
124
125 ret = sig_sem(SEM_FILEDESC);
126 if (ret < 0) {
127 syslog(LOG_ERROR, "sig_sem => %d", ret);
128 }
129
130 return fp;
131}
132
133int delete_fd_by_id(IO_TYPE *type, int id)
134{
135 struct SHELL_FILE *fp = id_to_fd(type, id);
136 if (fp == NULL)
137 return -EBADF;
138
139 return delete_fp(fp);
140}
141
142int delete_fp(struct SHELL_FILE *fp)
143{
144 ER ret;
145
146 fp->type->delete(fp);
147
148 ret = wai_sem(SEM_FILEDESC);
149 if (ret < 0) {
150 syslog(LOG_ERROR, "wai_sem => %d", ret);
151 }
152
153 memset(fp, 0, sizeof(struct SHELL_FILE));
154
155 ret = sig_sem(SEM_FILEDESC);
156 if (ret < 0) {
157 syslog(LOG_ERROR, "sig_sem => %d", ret);
158 }
159
160 return 0;
161}
162
163struct SHELL_FILE *fd_to_fp(int fd)
164{
165 if ((fd < 0) || (fd >= fd_table_count))
166 return NULL;
167 return &fd_table[fd];
168}
169
170void memand(void *dst, void *src, size_t len)
171{
172 uint8_t *d = (uint8_t *)dst;
173 uint8_t *s = (uint8_t *)src;
174 uint8_t *e = &s[len];
175
176 while (s < e) {
177 *d++ &= *s++;
178 }
179}
180
181struct fd_events {
182 int count;
183 fd_set readfds;
184 fd_set writefds;
185 fd_set errorfds;
186};
187
188ER shell_get_evts(struct fd_events *evts, TMO tmout);
189
190#define TMO_MAX INT_MAX
191
192int shell_select(int n, fd_set *__restrict rfds, fd_set *__restrict wfds, fd_set *__restrict efds, struct timeval *__restrict tv)
193{
194 ER ret;
195 TMO tmout = TMO_FEVR;
196 struct fd_events evts;
197
198 if (tv != NULL) {
199 if (tv->tv_sec < (TMO_MAX / 1000000))
200 tmout = tv->tv_sec * 1000000 + tv->tv_usec;
201 else
202 tmout = TMO_MAX;
203 }
204
205 if (rfds != NULL)
206 memcpy(&evts.readfds, rfds, sizeof(fd_set));
207 else
208 memset(&evts.readfds, 0, sizeof(fd_set));
209 if (wfds != NULL)
210 memcpy(&evts.writefds, wfds, sizeof(fd_set));
211 else
212 memset(&evts.writefds, 0, sizeof(fd_set));
213 if (efds != NULL)
214 memcpy(&evts.errorfds, efds, sizeof(fd_set));
215 else
216 memset(&evts.errorfds, 0, sizeof(fd_set));
217 evts.count = 0;
218
219 ret = shell_get_evts(&evts, tmout);
220 if (ret == E_OK) {
221 if (rfds != NULL)
222 memand(rfds, &evts.readfds, sizeof(fd_set));
223 if (wfds != NULL)
224 memand(wfds, &evts.writefds, sizeof(fd_set));
225 if (efds != NULL)
226 memand(efds, &evts.errorfds, sizeof(fd_set));
227 return evts.count;
228 }
229 if (ret == E_TMOUT) {
230 if (rfds != NULL)
231 memset(rfds, 0, sizeof(fd_set));
232 if (wfds != NULL)
233 memset(wfds, 0, sizeof(fd_set));
234 if (efds != NULL)
235 memset(efds, 0, sizeof(fd_set));
236 return 0;
237 }
238
239 return -EBADF;
240}
241
242int shell_poll(struct pollfd *fds, nfds_t nfds, int timeout)
243{
244 ER ret;
245 TMO tmout;
246 struct fd_events evts;
247
248 if(timeout < 0)
249 tmout = TMO_FEVR;
250 else if (timeout < (TMO_MAX / 1000))
251 tmout = timeout * 1000;
252 else
253 tmout = TMO_MAX;
254
255 memset(&evts, 0, sizeof(evts));
256
257 for (int i = 0; i < nfds; i++) {
258 struct pollfd *pfd = &fds[i];
259 int fd = pfd->fd;
260 if ((fd < 0) || (fd >= fd_table_count))
261 continue;
262
263 if (pfd->events & POLLIN)
264 FD_SET(fd, &evts.readfds);
265 if (pfd->events & POLLOUT)
266 FD_SET(fd, &evts.writefds);
267 if (pfd->events & POLLERR)
268 FD_SET(fd, &evts.errorfds);
269 pfd->revents = 0;
270 }
271
272 ret = shell_get_evts(&evts, tmout);
273 if (ret == E_OK) {
274 int result = 0;
275 for (int i = 0; i < nfds; i++) {
276 struct pollfd *pfd = &fds[i];
277 int fd = pfd->fd;
278 if ((fd < 0) || (fd >= fd_table_count))
279 continue;
280
281 if (FD_ISSET(fd, &evts.readfds))
282 pfd->revents |= POLLIN;
283 if (FD_ISSET(fd, &evts.writefds))
284 pfd->revents |= POLLOUT;
285 if (FD_ISSET(fd, &evts.errorfds))
286 pfd->revents |= POLLERR;
287 if (pfd->revents != 0)
288 result++;
289 }
290 return result;
291 }
292 if (ret == E_TMOUT) {
293 return 0;
294 }
295
296 return -EBADF;
297}
298
299ER shell_get_evts(struct fd_events *evts, TMO tmout)
300{
301 int count = 0;
302 SYSTIM prev, now;
303 FLGPTN flgptn;
304
305 get_tim(&prev);
306
307 for (;;) {
308 ER ret;
309 FLGPTN waitptn, readfds = 0, writefds = 0;
310 struct SHELL_FILE *fp = NULL;
311
312#ifndef NTSHELL_NO_SOCKET
313 waitptn = *((FLGPTN *)&evts->errorfds);
314#else
315 waitptn = *((FLGPTN *)&evts->readfds) | *((FLGPTN *)&evts->errorfds);
316#endif
317 for (int fd = 0; fd < fd_table_count; fd++) {
318 fp = &fd_table[fd];
319
320 if (FD_ISSET(fd, &evts->readfds)) {
321 if (fp->type->readable(fp)) {
322 FD_SET(fd, (fd_set *)&readfds);
323 count++;
324 if (fp->readevt_w == fp->readevt_r) fp->readevt_r--;
325 }
326 else {
327 FD_SET(fd, (fd_set *)&waitptn);
328 }
329 }
330
331 if (FD_ISSET(fd, &evts->writefds)) {
332 if (fp->type->writable(fp)) {
333 FD_SET(fd, (fd_set *)&writefds);
334 count++;
335 if (fp->writeevt_w == fp->writeevt_r) fp->writeevt_r--;
336 }
337 else {
338 FD_SET(fd, (fd_set *)&waitptn);
339 }
340 }
341 }
342 memset(evts, 0, sizeof(*evts));
343
344 if (waitptn == 0) {
345 memcpy(&evts->readfds, &readfds, sizeof(evts->readfds));
346 memcpy(&evts->writefds, &writefds, sizeof(evts->writefds));
347 evts->count = count;
348 return E_OK;
349 }
350 else if ((readfds | writefds) != 0) {
351 set_flg(FLG_SELECT_WAIT, (readfds | writefds));
352 }
353
354 /* イベント待ち */
355 flgptn = 0;
356 ret = twai_flg(FLG_SELECT_WAIT, waitptn, TWF_ORW, &flgptn, tmout);
357 if (ret != E_OK) {
358 if (ret != E_TMOUT) {
359 syslog(LOG_ERROR, "twai_flg => %d", ret);
360 return ret;
361 }
362 }
363
364 if (flgptn != 0) {
365 flgptn &= waitptn;
366
367 /* 受け取ったフラグのみクリア */
368 ret = clr_flg(FLG_SELECT_WAIT, ~flgptn);
369 if (ret != E_OK) {
370 syslog(LOG_ERROR, "clr_flg => %d", ret);
371 }
372 }
373
374 count = 0;
375 for (int fd = 0; fd < fd_table_count; fd++) {
376 fp = &fd_table[fd];
377
378 if (fp->readevt_w != fp->readevt_r) {
379 fp->readevt_r++;
380 if (FD_ISSET(fd, (fd_set *)&waitptn))
381 FD_SET(fd, &evts->readfds);
382 count++;
383 }
384 if (fp->writeevt_w != fp->writeevt_r) {
385 fp->writeevt_r++;
386 if (FD_ISSET(fd, (fd_set *)&waitptn))
387 FD_SET(fd, &evts->writefds);
388 count++;
389 }
390 if (fp->errorevt_w != fp->errorevt_r) {
391 fp->errorevt_r++;
392 if (FD_ISSET(fd, (fd_set *)&waitptn))
393 FD_SET(fd, &evts->errorfds);
394 count++;
395 }
396 }
397
398 if ((flgptn == 0) || (count > 0))
399 break;
400
401 get_tim(&now);
402
403 SYSTIM elapse = now - prev;
404 if (elapse > tmout) {
405 flgptn = 0;
406 break;
407 }
408
409 prev = now;
410 tmout -= elapse;
411 }
412
413 evts->count = count;
414
415 return (flgptn == 0) ? E_TMOUT : E_OK;
416}
417
418void clean_fd()
419{
420 struct SHELL_FILE *fp = NULL;
421 for (int fd = 3; fd < fd_table_count; fd++) {
422 fp = &fd_table[fd];
423 if ((fp->type == 0) || (fp->fd == 0))
424 continue;
425
426 fp->type->close(fp);
427
428 delete_fp(fp);
429 }
430}
431
432int shell_ioctl(int fd, int request, void *arg)
433{
434 struct SHELL_FILE *fp = fd_to_fp(fd);
435 if (fp == NULL)
436 return -EBADF;
437
438 return fp->type->ioctl(fp, request, arg);
439}
440
441#ifdef NTSHELL_NO_SOCKET
442
443int shell_socket(int family, int type, int protocol)
444{
445 return -ENOMEM;
446}
447
448int shell_bind(int fd, const struct sockaddr *addr, socklen_t len)
449{
450 return -ENOMEM;
451}
452
453int shell_listen(int fd, int backlog)
454{
455 return -ENOMEM;
456}
457
458int shell_connect(int fd, const struct sockaddr *addr, socklen_t len)
459{
460 return -ENOMEM;
461}
462
463int shell_accept(int fd, struct sockaddr *__restrict addr, socklen_t *__restrict len)
464{
465 return -ENOMEM;
466}
467
468ssize_t shell_sendto(int fd, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t alen)
469{
470 return -ENOMEM;
471}
472
473ssize_t shell_sendmsg(int fd, const struct msghdr *msg, int flags)
474{
475 return -ENOMEM;
476}
477
478ssize_t shell_recvfrom(int fd, void *__restrict buf, size_t len, int flags, struct sockaddr *__restrict addr, socklen_t *__restrict alen)
479{
480 return -ENOMEM;
481}
482
483ssize_t shell_recvmsg(int fd, struct msghdr *msg, int flags)
484{
485 return -ENOMEM;
486}
487
488int shell_shutdown(int fd, int how)
489{
490 return -ENOMEM;
491}
492
493int shell_getsockopt(int fd, int level, int optname, void *optval, socklen_t *__restrict optlen)
494{
495 return -ENOMEM;
496}
497
498int shell_setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen)
499{
500 return -ENOMEM;
501}
502
503int shell_getpeername(int fd, struct sockaddr *restrict addr, socklen_t *restrict len)
504{
505 return -ENOMEM;
506}
507
508int shell_getsockname(int fd, struct sockaddr *restrict addr, socklen_t *restrict len)
509{
510 return -ENOMEM;
511}
512#endif
Note: See TracBrowser for help on using the repository browser.