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