summaryrefslogtreecommitdiff
path: root/src/libpcp_trace/src/pdubuf.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libpcp_trace/src/pdubuf.c')
-rw-r--r--src/libpcp_trace/src/pdubuf.c182
1 files changed, 182 insertions, 0 deletions
diff --git a/src/libpcp_trace/src/pdubuf.c b/src/libpcp_trace/src/pdubuf.c
new file mode 100644
index 0000000..0440275
--- /dev/null
+++ b/src/libpcp_trace/src/pdubuf.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 1995 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "trace.h"
+#include "trace_dev.h"
+
+
+typedef struct bufctl {
+ struct bufctl *bc_next;
+ int bc_size;
+ int bc_pincnt;
+ char *bc_buf;
+ char *bc_bufend;
+} bufctl_t;
+
+static bufctl_t *buf_free;
+static bufctl_t *buf_pin;
+static bufctl_t *buf_pin_tail;
+
+#ifdef PMTRACE_DEBUG
+static void
+pdubufdump(void)
+{
+ bufctl_t *pcp;
+
+ if (buf_free != NULL) {
+ fprintf(stderr, " free pdubuf[size]:");
+ for (pcp = buf_free; pcp != NULL; pcp = pcp->bc_next)
+ fprintf(stderr, " 0x%p[%d]", pcp->bc_buf, pcp->bc_size);
+ fputc('\n', stderr);
+ }
+
+ if (buf_pin != NULL) {
+ fprintf(stderr, " pinned pdubuf[pincnt]:");
+ for (pcp = buf_pin; pcp != NULL; pcp = pcp->bc_next)
+ fprintf(stderr, " 0x%p[%d]", pcp->bc_buf, pcp->bc_pincnt);
+ fputc('\n', stderr);
+ }
+}
+#endif
+
+__pmTracePDU *
+__pmtracefindPDUbuf(int need)
+{
+ bufctl_t *pcp;
+
+ for (pcp = buf_free; pcp != NULL; pcp = pcp->bc_next) {
+ if (pcp->bc_size >= need)
+ break;
+ }
+ if (pcp == NULL) {
+ if ((pcp = (bufctl_t *)malloc(sizeof(*pcp))) == NULL)
+ return NULL;
+ pcp->bc_pincnt = 0;
+ pcp->bc_size = TRACE_PDU_CHUNK * (1 + need/TRACE_PDU_CHUNK);
+ if ((pcp->bc_buf = (char *)valloc(pcp->bc_size)) == NULL) {
+ free(pcp);
+ return NULL;
+ }
+ pcp->bc_next = buf_free;
+ pcp->bc_bufend = &pcp->bc_buf[pcp->bc_size];
+ buf_free = pcp;
+ }
+
+#ifdef PMTRACE_DEBUG
+ if (__pmstate & PMTRACE_STATE_PDUBUF) {
+ fprintf(stderr, "__pmtracefindPDUbuf(%d) -> 0x%p\n", need, pcp->bc_buf);
+ pdubufdump();
+ }
+#endif
+
+ return (__pmTracePDU *)pcp->bc_buf;
+}
+
+void
+__pmtracepinPDUbuf(void *handle)
+{
+ bufctl_t *pcp;
+ bufctl_t *prior = NULL;
+
+ for (pcp = buf_free; pcp != NULL; pcp = pcp->bc_next) {
+ if (pcp->bc_buf <= (char *)handle && (char *)handle < pcp->bc_bufend)
+ break;
+ prior = pcp;
+ }
+
+ if (pcp != NULL) {
+ /* first pin for this buffer, move between lists */
+ if (prior == NULL)
+ buf_free = pcp->bc_next;
+ else
+ prior->bc_next = pcp->bc_next;
+ pcp->bc_next = NULL;
+ if (buf_pin_tail != NULL)
+ buf_pin_tail->bc_next = pcp;
+ buf_pin_tail = pcp;
+ if (buf_pin == NULL)
+ buf_pin = pcp;
+ pcp->bc_pincnt = 1;
+ }
+ else {
+ for (pcp = buf_pin; pcp != NULL; pcp = pcp->bc_next) {
+ if (pcp->bc_buf <= (char *)handle && (char *)handle < pcp->bc_bufend)
+ break;
+ }
+ if (pcp != NULL)
+ pcp->bc_pincnt++;
+ else {
+#ifdef PMTRACE_DEBUG
+ if (__pmstate & PMTRACE_STATE_PDUBUF) {
+ fprintf(stderr, "__pmtracepinPDUbuf: 0x%p not in pool!", handle);
+ pdubufdump();
+ }
+#endif
+ return;
+ }
+ }
+
+#ifdef PMTRACE_DEBUG
+ if (__pmstate & PMTRACE_STATE_PDUBUF)
+ fprintf(stderr, "__pmtracepinPDUbuf(0x%p) -> pdubuf=0x%p, cnt=%d\n",
+ handle, pcp->bc_buf, pcp->bc_pincnt);
+#endif
+ return;
+}
+
+int
+__pmtraceunpinPDUbuf(void *handle)
+{
+ bufctl_t *pcp;
+ bufctl_t *prior = NULL;
+
+ for (pcp = buf_pin; pcp != NULL; pcp = pcp->bc_next) {
+ if (pcp->bc_buf <= (char *)handle && (char *)handle < &pcp->bc_buf[pcp->bc_size])
+ break;
+ prior = pcp;
+ }
+ if (pcp == NULL) {
+#ifdef PMTRACE_DEBUG
+ if (__pmstate & PMTRACE_STATE_PDUBUF) {
+ fprintf(stderr, "__pmtraceunpinPDUbuf(0x%p) -> fails\n", handle);
+ pdubufdump();
+ }
+#endif
+ return 0;
+ }
+
+ if (--pcp->bc_pincnt == 0) {
+ if (prior == NULL)
+ buf_pin = pcp->bc_next;
+ else
+ prior->bc_next = pcp->bc_next;
+ if (buf_pin_tail == pcp)
+ buf_pin_tail = prior;
+
+ pcp->bc_next = buf_free;
+ buf_free = pcp;
+ }
+
+#ifdef PMTRACE_DEBUG
+ if (__pmstate & PMTRACE_STATE_PDUBUF)
+ fprintf(stderr, "__pmtraceunpinPDUbuf(0x%p) -> pdubuf=0x%p, pincnt=%d\n",
+ handle, pcp->bc_buf, pcp->bc_pincnt);
+#endif
+
+ return 1;
+}