1d27927f7SRuslan Bukin /*-
2d27927f7SRuslan Bukin * Copyright (c) 2003-2008 Joseph Koshy
3d27927f7SRuslan Bukin * All rights reserved.
4d27927f7SRuslan Bukin *
5d27927f7SRuslan Bukin * Redistribution and use in source and binary forms, with or without
6d27927f7SRuslan Bukin * modification, are permitted provided that the following conditions
7d27927f7SRuslan Bukin * are met:
8d27927f7SRuslan Bukin * 1. Redistributions of source code must retain the above copyright
9d27927f7SRuslan Bukin * notice, this list of conditions and the following disclaimer.
10d27927f7SRuslan Bukin * 2. Redistributions in binary form must reproduce the above copyright
11d27927f7SRuslan Bukin * notice, this list of conditions and the following disclaimer in the
12d27927f7SRuslan Bukin * documentation and/or other materials provided with the distribution.
13d27927f7SRuslan Bukin *
14d27927f7SRuslan Bukin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15d27927f7SRuslan Bukin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16d27927f7SRuslan Bukin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17d27927f7SRuslan Bukin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18d27927f7SRuslan Bukin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19d27927f7SRuslan Bukin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20d27927f7SRuslan Bukin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21d27927f7SRuslan Bukin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22d27927f7SRuslan Bukin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23d27927f7SRuslan Bukin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24d27927f7SRuslan Bukin * SUCH DAMAGE.
25d27927f7SRuslan Bukin */
26d27927f7SRuslan Bukin
27d27927f7SRuslan Bukin #include <sys/types.h>
28d27927f7SRuslan Bukin #include <sys/cpuset.h>
29d27927f7SRuslan Bukin #include <sys/param.h>
30d27927f7SRuslan Bukin #include <sys/stat.h>
31d27927f7SRuslan Bukin #include <sys/pmc.h>
32d27927f7SRuslan Bukin
33d27927f7SRuslan Bukin #include <assert.h>
34d27927f7SRuslan Bukin #include <err.h>
35d27927f7SRuslan Bukin #include <errno.h>
36d27927f7SRuslan Bukin #include <pmc.h>
37d27927f7SRuslan Bukin #include <pmclog.h>
38d27927f7SRuslan Bukin #include <stdio.h>
39d27927f7SRuslan Bukin #include <stdlib.h>
40d27927f7SRuslan Bukin #include <string.h>
41d27927f7SRuslan Bukin #include <sysexits.h>
42d27927f7SRuslan Bukin
43d27927f7SRuslan Bukin #include "libpmcstat.h"
44d27927f7SRuslan Bukin
45d27927f7SRuslan Bukin static LIST_HEAD(,pmcstat_string) pmcstat_string_hash[PMCSTAT_NHASH];
46d27927f7SRuslan Bukin
47d27927f7SRuslan Bukin /*
48d27927f7SRuslan Bukin * Intern a copy of string 's', and return a pointer to the
49d27927f7SRuslan Bukin * interned structure.
50d27927f7SRuslan Bukin */
51d27927f7SRuslan Bukin
52d27927f7SRuslan Bukin pmcstat_interned_string
pmcstat_string_intern(const char * s)53d27927f7SRuslan Bukin pmcstat_string_intern(const char *s)
54d27927f7SRuslan Bukin {
55d27927f7SRuslan Bukin struct pmcstat_string *ps;
56d27927f7SRuslan Bukin const struct pmcstat_string *cps;
57d27927f7SRuslan Bukin int hash, len;
58d27927f7SRuslan Bukin
59d27927f7SRuslan Bukin if ((cps = pmcstat_string_lookup(s)) != NULL)
60d27927f7SRuslan Bukin return (cps);
61d27927f7SRuslan Bukin
62d27927f7SRuslan Bukin hash = pmcstat_string_compute_hash(s);
63d27927f7SRuslan Bukin len = strlen(s);
64d27927f7SRuslan Bukin
65d27927f7SRuslan Bukin if ((ps = malloc(sizeof(*ps))) == NULL)
66d27927f7SRuslan Bukin err(EX_OSERR, "ERROR: Could not intern string");
67d27927f7SRuslan Bukin ps->ps_len = len;
68d27927f7SRuslan Bukin ps->ps_hash = hash;
69d27927f7SRuslan Bukin ps->ps_string = strdup(s);
70d27927f7SRuslan Bukin LIST_INSERT_HEAD(&pmcstat_string_hash[hash], ps, ps_next);
71d27927f7SRuslan Bukin return ((pmcstat_interned_string) ps);
72d27927f7SRuslan Bukin }
73d27927f7SRuslan Bukin
74d27927f7SRuslan Bukin const char *
pmcstat_string_unintern(pmcstat_interned_string str)75d27927f7SRuslan Bukin pmcstat_string_unintern(pmcstat_interned_string str)
76d27927f7SRuslan Bukin {
77d27927f7SRuslan Bukin const char *s;
78d27927f7SRuslan Bukin
79d27927f7SRuslan Bukin s = ((const struct pmcstat_string *) str)->ps_string;
80d27927f7SRuslan Bukin return (s);
81d27927f7SRuslan Bukin }
82d27927f7SRuslan Bukin
83d27927f7SRuslan Bukin /*
84d27927f7SRuslan Bukin * Compute a 'hash' value for a string.
85d27927f7SRuslan Bukin */
86d27927f7SRuslan Bukin
87d27927f7SRuslan Bukin int
pmcstat_string_compute_hash(const char * s)88d27927f7SRuslan Bukin pmcstat_string_compute_hash(const char *s)
89d27927f7SRuslan Bukin {
90d27927f7SRuslan Bukin unsigned hash;
91d27927f7SRuslan Bukin
92d27927f7SRuslan Bukin for (hash = 2166136261; *s; s++)
93d27927f7SRuslan Bukin hash = (hash ^ *s) * 16777619;
94d27927f7SRuslan Bukin
95d27927f7SRuslan Bukin return (hash & PMCSTAT_HASH_MASK);
96d27927f7SRuslan Bukin }
97d27927f7SRuslan Bukin
98d27927f7SRuslan Bukin pmcstat_interned_string
pmcstat_string_lookup(const char * s)99d27927f7SRuslan Bukin pmcstat_string_lookup(const char *s)
100d27927f7SRuslan Bukin {
101d27927f7SRuslan Bukin struct pmcstat_string *ps;
102d27927f7SRuslan Bukin int hash, len;
103d27927f7SRuslan Bukin
104d27927f7SRuslan Bukin hash = pmcstat_string_compute_hash(s);
105d27927f7SRuslan Bukin len = strlen(s);
106d27927f7SRuslan Bukin
107d27927f7SRuslan Bukin LIST_FOREACH(ps, &pmcstat_string_hash[hash], ps_next)
108d27927f7SRuslan Bukin if (ps->ps_len == len && ps->ps_hash == hash &&
109d27927f7SRuslan Bukin strcmp(ps->ps_string, s) == 0)
110d27927f7SRuslan Bukin return (ps);
111d27927f7SRuslan Bukin return (NULL);
112d27927f7SRuslan Bukin }
113d27927f7SRuslan Bukin
114d27927f7SRuslan Bukin int
pmcstat_string_lookup_hash(pmcstat_interned_string s)115d27927f7SRuslan Bukin pmcstat_string_lookup_hash(pmcstat_interned_string s)
116d27927f7SRuslan Bukin {
117d27927f7SRuslan Bukin const struct pmcstat_string *ps;
118d27927f7SRuslan Bukin
119d27927f7SRuslan Bukin ps = (const struct pmcstat_string *) s;
120d27927f7SRuslan Bukin return (ps->ps_hash);
121d27927f7SRuslan Bukin }
122d27927f7SRuslan Bukin
123d27927f7SRuslan Bukin /*
124d27927f7SRuslan Bukin * Destroy the string table, free'ing up space.
125d27927f7SRuslan Bukin */
126d27927f7SRuslan Bukin
127d27927f7SRuslan Bukin void
pmcstat_string_shutdown(void)128d27927f7SRuslan Bukin pmcstat_string_shutdown(void)
129d27927f7SRuslan Bukin {
130d27927f7SRuslan Bukin int i;
131d27927f7SRuslan Bukin struct pmcstat_string *ps, *pstmp;
132d27927f7SRuslan Bukin
133d27927f7SRuslan Bukin for (i = 0; i < PMCSTAT_NHASH; i++)
134d27927f7SRuslan Bukin LIST_FOREACH_SAFE(ps, &pmcstat_string_hash[i], ps_next,
135d27927f7SRuslan Bukin pstmp) {
136d27927f7SRuslan Bukin LIST_REMOVE(ps, ps_next);
137d27927f7SRuslan Bukin free(ps->ps_string);
138d27927f7SRuslan Bukin free(ps);
139d27927f7SRuslan Bukin }
140d27927f7SRuslan Bukin }
141d27927f7SRuslan Bukin
142d27927f7SRuslan Bukin /*
143d27927f7SRuslan Bukin * Initialize the string interning facility.
144d27927f7SRuslan Bukin */
145d27927f7SRuslan Bukin
146d27927f7SRuslan Bukin void
pmcstat_string_initialize(void)147d27927f7SRuslan Bukin pmcstat_string_initialize(void)
148d27927f7SRuslan Bukin {
149d27927f7SRuslan Bukin int i;
150d27927f7SRuslan Bukin
151d27927f7SRuslan Bukin for (i = 0; i < PMCSTAT_NHASH; i++)
152d27927f7SRuslan Bukin LIST_INIT(&pmcstat_string_hash[i]);
153d27927f7SRuslan Bukin }
154