1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "private.h"
6
7 #include <stdarg.h>
8 #include <stdlib.h>
9 #include <stdio.h>
10
11 #include <zircon/syscalls.h>
12 #include <zircon/syscalls/log.h>
13
14 #ifdef FDIO_LLDEBUG
15 #define LOGBUF_MAX (ZX_LOG_RECORD_MAX - sizeof(zx_log_record_t))
16
fdio_lldebug_log_write(const void * _data,size_t len)17 static ssize_t fdio_lldebug_log_write(const void* _data, size_t len) {
18 static thread_local struct {
19 zx_handle_t log;
20 uint32_t next;
21 char data[LOGBUF_MAX];
22 }* logbuf = NULL;
23
24 if (logbuf == NULL) {
25 if ((logbuf = calloc(1, sizeof(*logbuf))) == NULL) {
26 return len;
27 }
28 if (zx_debuglog_create(0, 0, &logbuf->log) != ZX_OK) {
29 free(logbuf);
30 logbuf = NULL;
31 return len;
32 }
33 }
34
35 const char* data = _data;
36 size_t r = len;
37 while (len-- > 0) {
38 char c = *data++;
39 if (c == '\n') {
40 zx_log_write(logbuf->log, logbuf->next, logbuf->data, 0);
41 logbuf->next = 0;
42 continue;
43 }
44 if (c < ' ') {
45 continue;
46 }
47 logbuf->data[logbuf->next++] = c;
48 if (logbuf->next == LOGBUF_MAX) {
49 zx_log_write(logbuf->log, logbuf->next, logbuf->data, 0);
50 logbuf->next = 0;
51 continue;
52 }
53 }
54 return r;
55 }
56
57 static unsigned debug_level = FDIO_LLDEBUG;
58
fdio_lldebug_printf(unsigned level,const char * fmt,...)59 void fdio_lldebug_printf(unsigned level, const char* fmt, ...) {
60 if (debug_level >= level) {
61 va_list ap;
62 char buf[128];
63 va_start(ap, fmt);
64 size_t sz = vsnprintf(buf, sizeof(buf), fmt, ap);
65 va_end(ap);
66 fdio_lldebug_log_write(buf, sz > sizeof(buf) ? sizeof(buf) : sz);
67 }
68 }
69 #endif
70
fdio_set_debug_level(unsigned level)71 void fdio_set_debug_level(unsigned level) {
72 #ifdef FDIO_LLDEBUG
73 debug_level = level;
74 #endif
75 }
76
77 #ifdef FDIO_ALLOCDEBUG
78
79 #define PSZ 128
80
81 static char POOL[PSZ * 256];
82 static char* NEXT = POOL;
83 static mtx_t pool_lock;
84
fdio_alloc(size_t n,size_t sz)85 void* fdio_alloc(size_t n, size_t sz) {
86 if ((n > 1) || (sz > PSZ)) {
87 return NULL;
88 }
89 void* ptr = NULL;
90 mtx_lock(&pool_lock);
91 if ((NEXT - POOL) < (int)sizeof(POOL)) {
92 ptr = NEXT;
93 NEXT += PSZ;
94 } else {
95 LOG(1, "fdio: OUT OF FDIO_T POOL SPACE\n");
96 }
97 mtx_unlock(&pool_lock);
98 LOG(5, "fdio: io: alloc: %p\n", ptr);
99 return ptr;
100 }
101 #endif
102
fdio_free(fdio_t * io)103 void fdio_free(fdio_t* io) {
104 LOG(5, "fdio: io: free: %p\n", io);
105 io->magic = 0xDEAD0123;
106 io->ops = NULL;
107 #ifndef FDIO_ALLOCDEBUG
108 free(io);
109 #endif
110 }
111