xref: /netbsd-src/common/lib/libc/gmon/mcount.c (revision c68df8acc16fc1a39f31a26ec651871b95855ca0)
1*c68df8acSchristos /*	$NetBSD: mcount.c,v 1.18 2024/02/23 13:32:28 christos Exp $	*/
237c9f0a6Schristos 
337c9f0a6Schristos /*
437c9f0a6Schristos  * Copyright (c) 2003, 2004 Wasabi Systems, Inc.
537c9f0a6Schristos  * All rights reserved.
637c9f0a6Schristos  *
737c9f0a6Schristos  * Written by Nathan J. Williams for Wasabi Systems, Inc.
837c9f0a6Schristos  *
937c9f0a6Schristos  * Redistribution and use in source and binary forms, with or without
1037c9f0a6Schristos  * modification, are permitted provided that the following conditions
1137c9f0a6Schristos  * are met:
1237c9f0a6Schristos  * 1. Redistributions of source code must retain the above copyright
1337c9f0a6Schristos  *    notice, this list of conditions and the following disclaimer.
1437c9f0a6Schristos  * 2. Redistributions in binary form must reproduce the above copyright
1537c9f0a6Schristos  *    notice, this list of conditions and the following disclaimer in the
1637c9f0a6Schristos  *    documentation and/or other materials provided with the distribution.
1737c9f0a6Schristos  * 3. All advertising materials mentioning features or use of this software
1837c9f0a6Schristos  *    must display the following acknowledgement:
1937c9f0a6Schristos  *	This product includes software developed for the NetBSD Project by
2037c9f0a6Schristos  *	Wasabi Systems, Inc.
2137c9f0a6Schristos  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
2237c9f0a6Schristos  *    or promote products derived from this software without specific prior
2337c9f0a6Schristos  *    written permission.
2437c9f0a6Schristos  *
2537c9f0a6Schristos  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
2637c9f0a6Schristos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2737c9f0a6Schristos  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2837c9f0a6Schristos  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
2937c9f0a6Schristos  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
3037c9f0a6Schristos  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
3137c9f0a6Schristos  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
3237c9f0a6Schristos  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
3337c9f0a6Schristos  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3437c9f0a6Schristos  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3537c9f0a6Schristos  * POSSIBILITY OF SUCH DAMAGE.
3637c9f0a6Schristos  */
3737c9f0a6Schristos 
3837c9f0a6Schristos /*-
3937c9f0a6Schristos  * Copyright (c) 1983, 1992, 1993
4037c9f0a6Schristos  *	The Regents of the University of California.  All rights reserved.
4137c9f0a6Schristos  *
4237c9f0a6Schristos  * Redistribution and use in source and binary forms, with or without
4337c9f0a6Schristos  * modification, are permitted provided that the following conditions
4437c9f0a6Schristos  * are met:
4537c9f0a6Schristos  * 1. Redistributions of source code must retain the above copyright
4637c9f0a6Schristos  *    notice, this list of conditions and the following disclaimer.
4737c9f0a6Schristos  * 2. Redistributions in binary form must reproduce the above copyright
4837c9f0a6Schristos  *    notice, this list of conditions and the following disclaimer in the
4937c9f0a6Schristos  *    documentation and/or other materials provided with the distribution.
5037c9f0a6Schristos  * 3. Neither the name of the University nor the names of its contributors
5137c9f0a6Schristos  *    may be used to endorse or promote products derived from this software
5237c9f0a6Schristos  *    without specific prior written permission.
5337c9f0a6Schristos  *
5437c9f0a6Schristos  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
5537c9f0a6Schristos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
5637c9f0a6Schristos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5737c9f0a6Schristos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
5837c9f0a6Schristos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
5937c9f0a6Schristos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
6037c9f0a6Schristos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
6137c9f0a6Schristos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
6237c9f0a6Schristos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
6337c9f0a6Schristos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
6437c9f0a6Schristos  * SUCH DAMAGE.
6537c9f0a6Schristos  */
6637c9f0a6Schristos 
6737c9f0a6Schristos #ifdef _KERNEL_OPT
6837c9f0a6Schristos #include "opt_multiprocessor.h"
6937c9f0a6Schristos #endif
7037c9f0a6Schristos 
711979ff4aSryo /* If building a standalone libkern, don't include mcount. */
721979ff4aSryo #if (!defined(_KERNEL) || defined(GPROF)) && !defined(_STANDALONE)
731979ff4aSryo 
7437c9f0a6Schristos #include <sys/cdefs.h>
7537c9f0a6Schristos #if !defined(lint) && !defined(_KERNEL) && defined(LIBC_SCCS)
7637c9f0a6Schristos #if 0
7737c9f0a6Schristos static char sccsid[] = "@(#)mcount.c	8.1 (Berkeley) 6/4/93";
7837c9f0a6Schristos #else
79*c68df8acSchristos __RCSID("$NetBSD: mcount.c,v 1.18 2024/02/23 13:32:28 christos Exp $");
8037c9f0a6Schristos #endif
8137c9f0a6Schristos #endif
8237c9f0a6Schristos 
8337c9f0a6Schristos #include <sys/param.h>
8437c9f0a6Schristos #include <sys/gmon.h>
85c2acaf5fSryo #include <sys/lock.h>
86567a3a02Sryo #include <sys/proc.h>
8737c9f0a6Schristos 
8891165a00Schristos #ifndef _KERNEL
8937c9f0a6Schristos #include "reentrant.h"
9091165a00Schristos #endif
9137c9f0a6Schristos 
921a5f018bSkamil #if defined(_REENTRANT) && !defined(_RUMPKERNEL)
9337c9f0a6Schristos extern thread_key_t _gmonkey;
9437c9f0a6Schristos extern struct gmonparam _gmondummy;
9537c9f0a6Schristos struct gmonparam *_m_gmon_alloc(void);
9637c9f0a6Schristos #endif
9737c9f0a6Schristos 
98567219e1Smatt _MCOUNT_DECL(u_long, u_long)
9937c9f0a6Schristos #ifdef _KERNEL
1005dd5d540Suwe     __attribute__((__no_instrument_function__))
101088af57aSuwe #endif
1025dd5d540Suwe     __used;
10337c9f0a6Schristos 
10498e9d5f9Schristos /* XXX: make these interfaces */
10598e9d5f9Schristos #ifdef _RUMPKERNEL
10698e9d5f9Schristos #undef MCOUNT_ENTER
10798e9d5f9Schristos #define MCOUNT_ENTER
10898e9d5f9Schristos #undef MCOUNT_EXIT
10998e9d5f9Schristos #define MCOUNT_EXIT
11098e9d5f9Schristos #undef MCOUNT
11198e9d5f9Schristos #define MCOUNT
11298e9d5f9Schristos #endif
11398e9d5f9Schristos 
11437c9f0a6Schristos /*
11537c9f0a6Schristos  * mcount is called on entry to each function compiled with the profiling
11637c9f0a6Schristos  * switch set.  _mcount(), which is declared in a machine-dependent way
11737c9f0a6Schristos  * with _MCOUNT_DECL, does the actual work and is either inlined into a
11837c9f0a6Schristos  * C routine or called by an assembly stub.  In any case, this magic is
11937c9f0a6Schristos  * taken care of by the MCOUNT definition in <machine/profile.h>.
12037c9f0a6Schristos  *
12137c9f0a6Schristos  * _mcount updates data structures that represent traversals of the
12237c9f0a6Schristos  * program's call graph edges.  frompc and selfpc are the return
12337c9f0a6Schristos  * address and function address that represents the given call graph edge.
12437c9f0a6Schristos  *
12537c9f0a6Schristos  * Note: the original BSD code used the same variable (frompcindex) for
12637c9f0a6Schristos  * both frompcindex and frompc.  Any reasonable, modern compiler will
12737c9f0a6Schristos  * perform this optimization.
12837c9f0a6Schristos  */
129567219e1Smatt /* _mcount; may be static, inline, etc */
130*c68df8acSchristos /*LINTED unused*/
_MCOUNT_DECL(u_long frompc,u_long selfpc)131567219e1Smatt _MCOUNT_DECL(u_long frompc, u_long selfpc)
13237c9f0a6Schristos {
13337c9f0a6Schristos 	u_short *frompcindex;
13437c9f0a6Schristos 	struct tostruct *top, *prevtop;
13537c9f0a6Schristos 	struct gmonparam *p;
13637c9f0a6Schristos 	long toindex;
1371ce85336Spooka #if defined(_KERNEL) && !defined(_RUMPKERNEL)
13837c9f0a6Schristos 	int s;
13937c9f0a6Schristos #endif
14037c9f0a6Schristos 
1411a5f018bSkamil #if defined(_REENTRANT) && !defined(_KERNEL) && !defined(_RUMPKERNEL)
14237c9f0a6Schristos 	if (__isthreaded) {
14352ae8af9Schristos 		/* prevent re-entry via thr_getspecific */
14452ae8af9Schristos 		if (_gmonparam.state != GMON_PROF_ON)
14552ae8af9Schristos 			return;
14652ae8af9Schristos 		_gmonparam.state = GMON_PROF_BUSY;
14737c9f0a6Schristos 		p = thr_getspecific(_gmonkey);
14837c9f0a6Schristos 		if (p == NULL) {
14937c9f0a6Schristos 			/* Prevent recursive calls while allocating */
15037c9f0a6Schristos 			thr_setspecific(_gmonkey, &_gmondummy);
15137c9f0a6Schristos 			p = _m_gmon_alloc();
15237c9f0a6Schristos 		}
15352ae8af9Schristos 		_gmonparam.state = GMON_PROF_ON;
15437c9f0a6Schristos 	} else
15537c9f0a6Schristos #endif
15637c9f0a6Schristos 		p = &_gmonparam;
15737c9f0a6Schristos 	/*
15837c9f0a6Schristos 	 * check that we are profiling
15937c9f0a6Schristos 	 * and that we aren't recursively invoked.
16037c9f0a6Schristos 	 */
16137c9f0a6Schristos 	if (p->state != GMON_PROF_ON)
16237c9f0a6Schristos 		return;
163c2acaf5fSryo #if defined(_KERNEL) && !defined(_RUMPKERNEL)
16437c9f0a6Schristos 	MCOUNT_ENTER;
165c2acaf5fSryo #ifdef MULTIPROCESSOR
166567a3a02Sryo 	p = curcpu()->ci_gmon;
167567a3a02Sryo 	if (p == NULL || p->state != GMON_PROF_ON) {
168567a3a02Sryo 		MCOUNT_EXIT;
169567a3a02Sryo 		return;
170567a3a02Sryo 	}
171c2acaf5fSryo #endif
17237c9f0a6Schristos #endif
17337c9f0a6Schristos 	p->state = GMON_PROF_BUSY;
17437c9f0a6Schristos 	/*
17537c9f0a6Schristos 	 * check that frompcindex is a reasonable pc value.
17637c9f0a6Schristos 	 * for example:	signal catchers get called from the stack,
17737c9f0a6Schristos 	 *		not from text space.  too bad.
17837c9f0a6Schristos 	 */
17937c9f0a6Schristos 	frompc -= p->lowpc;
18037c9f0a6Schristos 	if (frompc > p->textsize)
18137c9f0a6Schristos 		goto done;
18237c9f0a6Schristos 
18337c9f0a6Schristos #if (HASHFRACTION & (HASHFRACTION - 1)) == 0
18437c9f0a6Schristos 	if (p->hashfraction == HASHFRACTION)
18537c9f0a6Schristos 		frompcindex =
18637c9f0a6Schristos 		    &p->froms[
18737c9f0a6Schristos 		    (size_t)(frompc / (HASHFRACTION * sizeof(*p->froms)))];
18837c9f0a6Schristos 	else
18937c9f0a6Schristos #endif
19037c9f0a6Schristos 		frompcindex =
19137c9f0a6Schristos 		    &p->froms[
19237c9f0a6Schristos 		    (size_t)(frompc / (p->hashfraction * sizeof(*p->froms)))];
19337c9f0a6Schristos 	toindex = *frompcindex;
19437c9f0a6Schristos 	if (toindex == 0) {
19537c9f0a6Schristos 		/*
19637c9f0a6Schristos 		 *	first time traversing this arc
19737c9f0a6Schristos 		 */
19837c9f0a6Schristos 		toindex = ++p->tos[0].link;
19937c9f0a6Schristos 		if (toindex >= p->tolimit)
20037c9f0a6Schristos 			/* halt further profiling */
20137c9f0a6Schristos 			goto overflow;
20237c9f0a6Schristos 
20337c9f0a6Schristos 		*frompcindex = (u_short)toindex;
20437c9f0a6Schristos 		top = &p->tos[(size_t)toindex];
20537c9f0a6Schristos 		top->selfpc = selfpc;
20637c9f0a6Schristos 		top->count = 1;
20737c9f0a6Schristos 		top->link = 0;
20837c9f0a6Schristos 		goto done;
20937c9f0a6Schristos 	}
21037c9f0a6Schristos 	top = &p->tos[(size_t)toindex];
21137c9f0a6Schristos 	if (top->selfpc == selfpc) {
21237c9f0a6Schristos 		/*
21337c9f0a6Schristos 		 * arc at front of chain; usual case.
21437c9f0a6Schristos 		 */
21537c9f0a6Schristos 		top->count++;
21637c9f0a6Schristos 		goto done;
21737c9f0a6Schristos 	}
21837c9f0a6Schristos 	/*
21937c9f0a6Schristos 	 * have to go looking down chain for it.
22037c9f0a6Schristos 	 * top points to what we are looking at,
22137c9f0a6Schristos 	 * prevtop points to previous top.
22237c9f0a6Schristos 	 * we know it is not at the head of the chain.
22337c9f0a6Schristos 	 */
22437c9f0a6Schristos 	for (; /* goto done */; ) {
22537c9f0a6Schristos 		if (top->link == 0) {
22637c9f0a6Schristos 			/*
22737c9f0a6Schristos 			 * top is end of the chain and none of the chain
22837c9f0a6Schristos 			 * had top->selfpc == selfpc.
22937c9f0a6Schristos 			 * so we allocate a new tostruct
23037c9f0a6Schristos 			 * and link it to the head of the chain.
23137c9f0a6Schristos 			 */
23237c9f0a6Schristos 			toindex = ++p->tos[0].link;
23337c9f0a6Schristos 			if (toindex >= p->tolimit)
23437c9f0a6Schristos 				goto overflow;
23537c9f0a6Schristos 
23637c9f0a6Schristos 			top = &p->tos[(size_t)toindex];
23737c9f0a6Schristos 			top->selfpc = selfpc;
23837c9f0a6Schristos 			top->count = 1;
23937c9f0a6Schristos 			top->link = *frompcindex;
24037c9f0a6Schristos 			*frompcindex = (u_short)toindex;
24137c9f0a6Schristos 			goto done;
24237c9f0a6Schristos 		}
24337c9f0a6Schristos 		/*
24437c9f0a6Schristos 		 * otherwise, check the next arc on the chain.
24537c9f0a6Schristos 		 */
24637c9f0a6Schristos 		prevtop = top;
24737c9f0a6Schristos 		top = &p->tos[top->link];
24837c9f0a6Schristos 		if (top->selfpc == selfpc) {
24937c9f0a6Schristos 			/*
25037c9f0a6Schristos 			 * there it is.
25137c9f0a6Schristos 			 * increment its count
25237c9f0a6Schristos 			 * move it to the head of the chain.
25337c9f0a6Schristos 			 */
25437c9f0a6Schristos 			top->count++;
25537c9f0a6Schristos 			toindex = prevtop->link;
25637c9f0a6Schristos 			prevtop->link = top->link;
25737c9f0a6Schristos 			top->link = *frompcindex;
25837c9f0a6Schristos 			*frompcindex = (u_short)toindex;
25937c9f0a6Schristos 			goto done;
26037c9f0a6Schristos 		}
26137c9f0a6Schristos 	}
26237c9f0a6Schristos done:
26337c9f0a6Schristos 	p->state = GMON_PROF_ON;
264c2acaf5fSryo #if defined(_KERNEL) && !defined(_RUMPKERNEL)
26537c9f0a6Schristos 	MCOUNT_EXIT;
26637c9f0a6Schristos #endif
26737c9f0a6Schristos 	return;
268c2acaf5fSryo 
26937c9f0a6Schristos overflow:
27037c9f0a6Schristos 	p->state = GMON_PROF_ERROR;
271c2acaf5fSryo #if defined(_KERNEL) && !defined(_RUMPKERNEL)
27237c9f0a6Schristos 	MCOUNT_EXIT;
27337c9f0a6Schristos #endif
27437c9f0a6Schristos 	return;
27537c9f0a6Schristos }
27637c9f0a6Schristos 
27737c9f0a6Schristos #ifdef MCOUNT
27837c9f0a6Schristos /*
27937c9f0a6Schristos  * Actual definition of mcount function.  Defined in <machine/profile.h>,
28037c9f0a6Schristos  * which is included by <sys/gmon.h>.
28137c9f0a6Schristos  */
28237c9f0a6Schristos MCOUNT
28337c9f0a6Schristos #endif
28437c9f0a6Schristos 
285567a3a02Sryo #if defined(_KERNEL) && !defined(_RUMPKERNEL) && defined(MULTIPROCESSOR)
286567a3a02Sryo void _gmonparam_merge(struct gmonparam *, struct gmonparam *);
287567a3a02Sryo 
288567a3a02Sryo void
_gmonparam_merge(struct gmonparam * p,struct gmonparam * q)289567a3a02Sryo _gmonparam_merge(struct gmonparam *p, struct gmonparam *q)
290567a3a02Sryo {
291567a3a02Sryo 	u_long fromindex;
292567a3a02Sryo 	u_short *frompcindex, qtoindex, toindex;
293567a3a02Sryo 	u_long selfpc;
294567a3a02Sryo 	u_long endfrom;
295567a3a02Sryo 	long count;
296567a3a02Sryo 	struct tostruct *top;
297567a3a02Sryo 	int i;
298567a3a02Sryo 
299567a3a02Sryo 	count = q->kcountsize / sizeof(*q->kcount);
300567a3a02Sryo 	for (i = 0; i < count; i++)
301567a3a02Sryo 		p->kcount[i] += q->kcount[i];
302567a3a02Sryo 
303567a3a02Sryo 	endfrom = (q->fromssize / sizeof(*q->froms));
304567a3a02Sryo 	for (fromindex = 0; fromindex < endfrom; fromindex++) {
305567a3a02Sryo 		if (q->froms[fromindex] == 0)
306567a3a02Sryo 			continue;
307567a3a02Sryo 		for (qtoindex = q->froms[fromindex]; qtoindex != 0;
308567a3a02Sryo 		     qtoindex = q->tos[qtoindex].link) {
309567a3a02Sryo 			selfpc = q->tos[qtoindex].selfpc;
310567a3a02Sryo 			count = q->tos[qtoindex].count;
311567a3a02Sryo 			/* cribbed from mcount */
312567a3a02Sryo 			frompcindex = &p->froms[fromindex];
313567a3a02Sryo 			toindex = *frompcindex;
314567a3a02Sryo 			if (toindex == 0) {
315567a3a02Sryo 				/*
316567a3a02Sryo 				 * first time traversing this arc
317567a3a02Sryo 				 */
318567a3a02Sryo 				toindex = ++p->tos[0].link;
319567a3a02Sryo 				if (toindex >= p->tolimit)
320567a3a02Sryo 					/* halt further profiling */
321567a3a02Sryo 					goto overflow;
322567a3a02Sryo 
323567a3a02Sryo 				*frompcindex = (u_short)toindex;
324567a3a02Sryo 				top = &p->tos[(size_t)toindex];
325567a3a02Sryo 				top->selfpc = selfpc;
326567a3a02Sryo 				top->count = count;
327567a3a02Sryo 				top->link = 0;
328567a3a02Sryo 				goto done;
329567a3a02Sryo 			}
330567a3a02Sryo 			top = &p->tos[(size_t)toindex];
331567a3a02Sryo 			if (top->selfpc == selfpc) {
332567a3a02Sryo 				/*
333567a3a02Sryo 				 * arc at front of chain; usual case.
334567a3a02Sryo 				 */
335567a3a02Sryo 				top->count+= count;
336567a3a02Sryo 				goto done;
337567a3a02Sryo 			}
338567a3a02Sryo 			/*
339567a3a02Sryo 			 * have to go looking down chain for it.
340567a3a02Sryo 			 * top points to what we are looking at,
341567a3a02Sryo 			 * we know it is not at the head of the chain.
342567a3a02Sryo 			 */
343567a3a02Sryo 			for (; /* goto done */; ) {
344567a3a02Sryo 				if (top->link == 0) {
345567a3a02Sryo 					/*
346567a3a02Sryo 					 * top is end of the chain and
347567a3a02Sryo 					 * none of the chain had
348567a3a02Sryo 					 * top->selfpc == selfpc.  so
349567a3a02Sryo 					 * we allocate a new tostruct
350567a3a02Sryo 					 * and link it to the head of
351567a3a02Sryo 					 * the chain.
352567a3a02Sryo 					 */
353567a3a02Sryo 					toindex = ++p->tos[0].link;
354567a3a02Sryo 					if (toindex >= p->tolimit)
355567a3a02Sryo 						goto overflow;
356567a3a02Sryo 
357567a3a02Sryo 					top = &p->tos[(size_t)toindex];
358567a3a02Sryo 					top->selfpc = selfpc;
359567a3a02Sryo 					top->count = count;
360567a3a02Sryo 					top->link = *frompcindex;
361567a3a02Sryo 					*frompcindex = (u_short)toindex;
362567a3a02Sryo 					goto done;
363567a3a02Sryo 				}
364567a3a02Sryo 				/*
365567a3a02Sryo 				 * otherwise, check the next arc on the chain.
366567a3a02Sryo 				 */
367567a3a02Sryo 				top = &p->tos[top->link];
368567a3a02Sryo 				if (top->selfpc == selfpc) {
369567a3a02Sryo 					/*
370567a3a02Sryo 					 * there it is.
371567a3a02Sryo 					 * add to its count.
372567a3a02Sryo 					 */
373567a3a02Sryo 					top->count += count;
374567a3a02Sryo 					goto done;
375567a3a02Sryo 				}
376567a3a02Sryo 			}
377567a3a02Sryo 
378567a3a02Sryo 		done: ;
379567a3a02Sryo 		}
380567a3a02Sryo 
381567a3a02Sryo 	}
382567a3a02Sryo  overflow: ;
383567a3a02Sryo 
384567a3a02Sryo }
385567a3a02Sryo #endif
386567a3a02Sryo 
3878ca2029dSchristos #endif /* (!_KERNEL || GPROF) && !_STANDALONE */
388