1c6402783Sakolb /*
2c6402783Sakolb * CDDL HEADER START
3c6402783Sakolb *
4c6402783Sakolb * The contents of this file are subject to the terms of the
5c6402783Sakolb * Common Development and Distribution License (the "License").
6c6402783Sakolb * You may not use this file except in compliance with the License.
7c6402783Sakolb *
8c6402783Sakolb * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9c6402783Sakolb * or http://www.opensolaris.org/os/licensing.
10c6402783Sakolb * See the License for the specific language governing permissions
11c6402783Sakolb * and limitations under the License.
12c6402783Sakolb *
13c6402783Sakolb * When distributing Covered Code, include this CDDL HEADER in each
14c6402783Sakolb * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15c6402783Sakolb * If applicable, add the following below this CDDL HEADER, with the
16c6402783Sakolb * fields enclosed by brackets "[]" replaced with your own identifying
17c6402783Sakolb * information: Portions Copyright [yyyy] [name of copyright owner]
18c6402783Sakolb *
19c6402783Sakolb * CDDL HEADER END
20c6402783Sakolb */
21c6402783Sakolb
22c6402783Sakolb /*
23c6402783Sakolb * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
24c6402783Sakolb * Use is subject to license terms.
25c6402783Sakolb */
26c6402783Sakolb
27c6402783Sakolb /*
28c6402783Sakolb * Lgrp.xs contains XS wrappers for the system locality group library
29c6402783Sakolb * liblgrp(3LIB).
30c6402783Sakolb */
31c6402783Sakolb
32c6402783Sakolb #include <sys/errno.h>
33c6402783Sakolb #include <sys/lgrp_user.h>
34c6402783Sakolb
35c6402783Sakolb /*
36c6402783Sakolb * On i386 Solaris defines SP, which conflicts with the perl definition of SP
37c6402783Sakolb * We don't need the Solaris one, so get rid of it to avoid warnings.
38c6402783Sakolb */
39c6402783Sakolb #undef SP
40c6402783Sakolb
41c6402783Sakolb /* Perl XS includes. */
42c6402783Sakolb #include "EXTERN.h"
43c6402783Sakolb #include "perl.h"
44c6402783Sakolb #include "XSUB.h"
45c6402783Sakolb
46c6402783Sakolb /* Return undef in scalar context and empty list in list context */
47c6402783Sakolb #define LGRP_BADVAL() { \
48c6402783Sakolb if (GIMME_V == G_ARRAY) \
49c6402783Sakolb XSRETURN_EMPTY; \
50c6402783Sakolb else \
51c6402783Sakolb XSRETURN_UNDEF; \
52c6402783Sakolb }
53c6402783Sakolb
54c6402783Sakolb /*
55c6402783Sakolb * Push all values from input array onto the perl return stack.
56c6402783Sakolb */
57c6402783Sakolb #define PUSHARRAY(array, nitems) \
58c6402783Sakolb { \
59c6402783Sakolb int x; \
60c6402783Sakolb \
61c6402783Sakolb if (nitems < 0) { \
62c6402783Sakolb LGRP_BADVAL() \
63c6402783Sakolb } else if (nitems > 0) { \
64c6402783Sakolb EXTEND(SP, nitems); \
65c6402783Sakolb for (x = 0; x < nitems; x++) { \
66c6402783Sakolb PUSHs(sv_2mortal(newSVnv(array[x]))); \
67c6402783Sakolb } \
68c6402783Sakolb } \
69c6402783Sakolb }
70c6402783Sakolb
71c6402783Sakolb /*
72c6402783Sakolb * Several constants are not present in the first version of the Lgrp API,
73c6402783Sakolb * we define them here.
74c6402783Sakolb *
75c6402783Sakolb * lgrp_resources() and lgrp_latency_cookie() only appear in API v2. If the
76c6402783Sakolb * module is linked with old version of liblgrp(3LIB) there is no lgrp_resources
77c6402783Sakolb * symbol in the library and perl wrapper returns empty list and sets errno to
78c6402783Sakolb * EINVAL.
79c6402783Sakolb *
80c6402783Sakolb * The lgrp_latency_cookie() is emulated using lgrp_latency().
81c6402783Sakolb */
82c6402783Sakolb #if LGRP_VER_CURRENT == 1
83c6402783Sakolb #define LGRP_CONTENT_ALL LGRP_CONTENT_HIERARCHY
84c6402783Sakolb #define LGRP_LAT_CPU_TO_MEM 0
85c6402783Sakolb #define LGRP_RSRC_CPU 0 /* CPU resources */
86c6402783Sakolb #define LGRP_RSRC_MEM 1 /* memory resources */
87c6402783Sakolb
88c6402783Sakolb #define LGRP_RESOURCES(c, lgrp, type) \
89c6402783Sakolb { errno = EINVAL; LGRP_BADVAL(); }
90c6402783Sakolb
91c6402783Sakolb /*
92c6402783Sakolb * Simulate lgrp_latency_cookie() which just fails. This macro is never called
93c6402783Sakolb * and we just define it so that the C compiler will not complain about the
94c6402783Sakolb * missing symbol.
95c6402783Sakolb */
96c6402783Sakolb #define lgrp_latency_cookie(c, f, t, b) (errno = EINVAL, -1)
97c6402783Sakolb
98c6402783Sakolb #else
99c6402783Sakolb #define LGRP_RESOURCES(c, lgrp, type) { \
100c6402783Sakolb int nr; \
101c6402783Sakolb lgrp_id_t *lgrps; \
102c6402783Sakolb \
103c6402783Sakolb errno = 0; \
104c6402783Sakolb nr = lgrp_resources(c, lgrp, NULL, 0, type); \
105c6402783Sakolb if (nr < 0) \
106c6402783Sakolb LGRP_BADVAL(); \
107c6402783Sakolb if (GIMME_V == G_SCALAR) \
108c6402783Sakolb XSRETURN_IV(nr); \
109c6402783Sakolb if (nr == 0) { \
110c6402783Sakolb XSRETURN_EMPTY; \
111c6402783Sakolb } else if (New(0, lgrps, nr, lgrp_id_t) == NULL) { \
112c6402783Sakolb errno = ENOMEM; \
113c6402783Sakolb LGRP_BADVAL(); \
114c6402783Sakolb } else { \
115c6402783Sakolb nr = lgrp_resources(c, lgrp, lgrps, nr, type); \
116c6402783Sakolb PUSHARRAY(lgrps, nr); \
117c6402783Sakolb Safefree(lgrps); \
118c6402783Sakolb } \
119c6402783Sakolb }
120c6402783Sakolb #endif
121c6402783Sakolb
122c6402783Sakolb /*
123c6402783Sakolb * Special version of lgrp_latency_cookie(). Use lgrp_latency() for liblgrp V1
124c6402783Sakolb * and lgrp_latency_cookie for V2.
125c6402783Sakolb */
126c6402783Sakolb static int
_lgrp_latency_cookie(lgrp_cookie_t cookie,lgrp_id_t from,lgrp_id_t to,int between)127c6402783Sakolb _lgrp_latency_cookie(lgrp_cookie_t cookie, lgrp_id_t from, lgrp_id_t to,
128c6402783Sakolb int between)
129c6402783Sakolb {
130c6402783Sakolb return (LGRP_VER_CURRENT < 2 ?
131c6402783Sakolb lgrp_latency(from, to) :
132c6402783Sakolb lgrp_latency_cookie(cookie, from, to, between));
133c6402783Sakolb }
134c6402783Sakolb
135c6402783Sakolb /*
136c6402783Sakolb * Most functions in liblgrp return -1 on failure. The perl equivalent returns
137c6402783Sakolb * 'undef' instead. The macro should be call after the RETVAL is set to the
138c6402783Sakolb * return value of the function.
139c6402783Sakolb */
140c6402783Sakolb #define RETURN_UNDEF_IF_FAIL { if (RETVAL < 0) XSRETURN_UNDEF; }
141c6402783Sakolb
142c6402783Sakolb /*
143c6402783Sakolb * End of C part, start of XS part.
144c6402783Sakolb *
145c6402783Sakolb * The XS code exported to perl is below here. Note that the XS preprocessor
146c6402783Sakolb * has its own commenting syntax, so all comments from this point on are in
147c6402783Sakolb * that form.
148c6402783Sakolb */
149c6402783Sakolb
150c6402783Sakolb MODULE = Sun::Solaris::Lgrp PACKAGE = Sun::Solaris::Lgrp
151c6402783Sakolb PROTOTYPES: ENABLE
152c6402783Sakolb
153c6402783Sakolb #
154c6402783Sakolb # Define any constants that need to be exported. By doing it this way we can
155c6402783Sakolb # avoid the overhead of using the DynaLoader package, and in addition constants
156c6402783Sakolb # defined using this mechanism are eligible for inlining by the perl
157c6402783Sakolb # interpreter at compile time.
158c6402783Sakolb #
159c6402783Sakolb BOOT:
160c6402783Sakolb {
161c6402783Sakolb HV *stash;
162c6402783Sakolb
163c6402783Sakolb stash = gv_stashpv("Sun::Solaris::Lgrp", TRUE);
164c6402783Sakolb newCONSTSUB(stash, "LGRP_AFF_NONE", newSViv(LGRP_AFF_NONE));
165c6402783Sakolb newCONSTSUB(stash, "LGRP_AFF_STRONG", newSViv(LGRP_AFF_STRONG));
166c6402783Sakolb newCONSTSUB(stash, "LGRP_AFF_WEAK", newSViv(LGRP_AFF_WEAK));
167c6402783Sakolb newCONSTSUB(stash, "LGRP_VER_CURRENT", newSViv(LGRP_VER_CURRENT));
168c6402783Sakolb newCONSTSUB(stash, "LGRP_VER_NONE", newSViv(LGRP_VER_NONE));
169c6402783Sakolb newCONSTSUB(stash, "LGRP_NONE", newSViv(LGRP_NONE));
170c6402783Sakolb newCONSTSUB(stash, "LGRP_RSRC_CPU", newSViv(LGRP_RSRC_CPU));
171c6402783Sakolb newCONSTSUB(stash, "LGRP_RSRC_MEM", newSViv(LGRP_RSRC_MEM));
172c6402783Sakolb newCONSTSUB(stash, "LGRP_CONTENT_HIERARCHY",
173c6402783Sakolb newSViv(LGRP_CONTENT_HIERARCHY));
174c6402783Sakolb newCONSTSUB(stash, "LGRP_CONTENT_DIRECT", newSViv(LGRP_CONTENT_DIRECT));
175c6402783Sakolb newCONSTSUB(stash, "LGRP_VIEW_CALLER", newSViv(LGRP_VIEW_CALLER));
176c6402783Sakolb newCONSTSUB(stash, "LGRP_VIEW_OS", newSViv(LGRP_VIEW_OS));
177c6402783Sakolb newCONSTSUB(stash, "LGRP_MEM_SZ_FREE", newSViv(LGRP_MEM_SZ_FREE));
178c6402783Sakolb newCONSTSUB(stash, "LGRP_MEM_SZ_INSTALLED",
179c6402783Sakolb newSViv(LGRP_MEM_SZ_INSTALLED));
180c6402783Sakolb newCONSTSUB(stash, "LGRP_CONTENT_ALL", newSViv(LGRP_CONTENT_ALL));
181c6402783Sakolb newCONSTSUB(stash, "LGRP_LAT_CPU_TO_MEM", newSViv(LGRP_LAT_CPU_TO_MEM));
182c6402783Sakolb newCONSTSUB(stash, "P_PID", newSViv(P_PID));
183c6402783Sakolb newCONSTSUB(stash, "P_LWPID", newSViv(P_LWPID));
184c6402783Sakolb newCONSTSUB(stash, "P_MYID", newSViv(P_MYID));
185c6402783Sakolb }
186c6402783Sakolb
187c6402783Sakolb #
188c6402783Sakolb # The code below uses POSTCALL directive which allows to return 'undef'
189c6402783Sakolb # whenever a C function returns a negative value.
190c6402783Sakolb #
191c6402783Sakolb
192c6402783Sakolb
193c6402783Sakolb #
194c6402783Sakolb # lgrp_init([view])
195c6402783Sakolb # Use LGRP_VIEW_OS as the default view.
196c6402783Sakolb #
197c6402783Sakolb lgrp_cookie_t
198c6402783Sakolb lgrp_init(lgrp_view_t view = LGRP_VIEW_OS)
199c6402783Sakolb POSTCALL:
200c6402783Sakolb RETURN_UNDEF_IF_FAIL;
201c6402783Sakolb
202c6402783Sakolb lgrp_view_t
203c6402783Sakolb lgrp_view(cookie)
204c6402783Sakolb lgrp_cookie_t cookie
205c6402783Sakolb POSTCALL:
206c6402783Sakolb RETURN_UNDEF_IF_FAIL;
207c6402783Sakolb
208c6402783Sakolb lgrp_affinity_t
209c6402783Sakolb lgrp_affinity_get(idtype, id, lgrp)
210c6402783Sakolb idtype_t idtype;
211c6402783Sakolb id_t id;
212c6402783Sakolb lgrp_id_t lgrp;
213c6402783Sakolb POSTCALL:
214c6402783Sakolb RETURN_UNDEF_IF_FAIL;
215c6402783Sakolb
216c6402783Sakolb int
217c6402783Sakolb lgrp_affinity_set(idtype, id, lgrp, affinity)
218c6402783Sakolb idtype_t idtype;
219c6402783Sakolb id_t id;
220c6402783Sakolb lgrp_id_t lgrp;
221c6402783Sakolb lgrp_affinity_t affinity;
222c6402783Sakolb POSTCALL:
223c6402783Sakolb RETURN_UNDEF_IF_FAIL;
224c6402783Sakolb XSRETURN_YES;
225c6402783Sakolb
226c6402783Sakolb int
227c6402783Sakolb lgrp_cookie_stale(cookie)
228c6402783Sakolb lgrp_cookie_t cookie;
229c6402783Sakolb POSTCALL:
230c6402783Sakolb RETURN_UNDEF_IF_FAIL;
231c6402783Sakolb
232c6402783Sakolb int
233c6402783Sakolb lgrp_fini(cookie)
234c6402783Sakolb lgrp_cookie_t cookie;
235c6402783Sakolb POSTCALL:
236c6402783Sakolb RETURN_UNDEF_IF_FAIL;
237c6402783Sakolb XSRETURN_YES;
238c6402783Sakolb
239c6402783Sakolb lgrp_id_t
240c6402783Sakolb lgrp_home(idtype, id)
241c6402783Sakolb idtype_t idtype;
242c6402783Sakolb id_t id;
243c6402783Sakolb POSTCALL:
244c6402783Sakolb RETURN_UNDEF_IF_FAIL;
245c6402783Sakolb
246c6402783Sakolb int
247c6402783Sakolb lgrp_latency(lgrp_id_t from,lgrp_id_t to)
248c6402783Sakolb POSTCALL:
249c6402783Sakolb RETURN_UNDEF_IF_FAIL;
250c6402783Sakolb
251c6402783Sakolb lgrp_mem_size_t
252c6402783Sakolb lgrp_mem_size(cookie, lgrp, type, content)
253c6402783Sakolb lgrp_cookie_t cookie
254c6402783Sakolb lgrp_id_t lgrp
255c6402783Sakolb int type
256c6402783Sakolb lgrp_content_t content
257c6402783Sakolb POSTCALL:
258c6402783Sakolb RETURN_UNDEF_IF_FAIL;
259c6402783Sakolb
260c6402783Sakolb int
261c6402783Sakolb lgrp_nlgrps(cookie)
262c6402783Sakolb lgrp_cookie_t cookie;
263c6402783Sakolb POSTCALL:
264c6402783Sakolb RETURN_UNDEF_IF_FAIL;
265c6402783Sakolb
266c6402783Sakolb lgrp_id_t
267c6402783Sakolb lgrp_root(cookie)
268c6402783Sakolb lgrp_cookie_t cookie
269c6402783Sakolb POSTCALL:
270c6402783Sakolb RETURN_UNDEF_IF_FAIL;
271c6402783Sakolb
272c6402783Sakolb int
273c6402783Sakolb lgrp_version(int version = LGRP_VER_NONE)
274c6402783Sakolb
275c6402783Sakolb #
276c6402783Sakolb # lgrp_latency_cookie calls our internal wrapper _lgrp_latency_cookie() which
277c6402783Sakolb # works for both old and new versions of liblgrp.
278*2a8bcb4eSToomas Soome #
279c6402783Sakolb int
280c6402783Sakolb lgrp_latency_cookie(lgrp_cookie_t cookie, lgrp_id_t from, lgrp_id_t to, int between = 0)
281c6402783Sakolb CODE:
282c6402783Sakolb RETVAL = _lgrp_latency_cookie(cookie, from, to, between);
283c6402783Sakolb POSTCALL:
284c6402783Sakolb RETURN_UNDEF_IF_FAIL;
285c6402783Sakolb OUTPUT:
286c6402783Sakolb RETVAL
287c6402783Sakolb
288c6402783Sakolb #
289c6402783Sakolb # Functions below convert C arrays into Perl lists. They use XS PPCODE
290c6402783Sakolb # directive to avoid implicit RETVAL assignments and manipulate perl
291c6402783Sakolb # stack directly.
292c6402783Sakolb #
293c6402783Sakolb # When called in scalar context functions return the number of elements
294c6402783Sakolb # in the list or undef on failure.
295c6402783Sakolb #
296c6402783Sakolb # The PUSHARRAY() macro defined above pushes all values from the C array to
297c6402783Sakolb # the perl stack.
298c6402783Sakolb #
299c6402783Sakolb
300c6402783Sakolb #
301c6402783Sakolb # @children = lgrp_children($cookie, $parent).
302c6402783Sakolb #
303c6402783Sakolb void
304c6402783Sakolb lgrp_children(cookie, lgrp)
305c6402783Sakolb lgrp_cookie_t cookie;
306c6402783Sakolb lgrp_id_t lgrp;
307c6402783Sakolb PREINIT:
308c6402783Sakolb lgrp_id_t *lgrps;
309c6402783Sakolb int count;
310c6402783Sakolb PPCODE:
311c6402783Sakolb errno = 0;
312c6402783Sakolb if ((count = lgrp_children(cookie, lgrp, NULL, 0)) < 0)
313c6402783Sakolb LGRP_BADVAL();
314c6402783Sakolb
315c6402783Sakolb if (GIMME_V == G_SCALAR)
316c6402783Sakolb XSRETURN_IV(count);
317c6402783Sakolb
318c6402783Sakolb if (count > 0) {
319c6402783Sakolb if (New(0, lgrps, count, lgrp_id_t) == NULL) {
320c6402783Sakolb errno = ENOMEM;
321c6402783Sakolb LGRP_BADVAL();
322c6402783Sakolb } else {
323c6402783Sakolb count = lgrp_children(cookie, lgrp, lgrps, count);
324c6402783Sakolb PUSHARRAY(lgrps, count);
325c6402783Sakolb Safefree(lgrps);
326c6402783Sakolb }
327c6402783Sakolb }
328c6402783Sakolb
329c6402783Sakolb #
330c6402783Sakolb # @parents = lgrp_parents($cookie, $lgrp).
331c6402783Sakolb #
332c6402783Sakolb void
333c6402783Sakolb lgrp_parents(cookie, lgrp)
334c6402783Sakolb lgrp_cookie_t cookie;
335c6402783Sakolb lgrp_id_t lgrp;
336c6402783Sakolb PREINIT:
337c6402783Sakolb lgrp_id_t *lgrps;
338c6402783Sakolb int count;
339c6402783Sakolb PPCODE:
340c6402783Sakolb errno = 0;
341c6402783Sakolb if ((count = lgrp_parents(cookie, lgrp, NULL, 0)) < 0)
342c6402783Sakolb LGRP_BADVAL();
343c6402783Sakolb
344c6402783Sakolb if (GIMME_V == G_SCALAR)
345c6402783Sakolb XSRETURN_IV(count);
346c6402783Sakolb
347c6402783Sakolb if (count > 0) {
348c6402783Sakolb if (New(0, lgrps, count, lgrp_id_t) == NULL) {
349c6402783Sakolb errno = ENOMEM;
350c6402783Sakolb LGRP_BADVAL();
351c6402783Sakolb } else {
352c6402783Sakolb count = lgrp_parents(cookie, lgrp, lgrps, count);
353c6402783Sakolb PUSHARRAY(lgrps, count);
354c6402783Sakolb Safefree(lgrps);
355c6402783Sakolb }
356c6402783Sakolb }
357c6402783Sakolb
358c6402783Sakolb #
359c6402783Sakolb # @parents = lgrp_cpus($cookie, $lgrp, $content).
360c6402783Sakolb # Content should be LGRP_CONTENT_HIERARCHY or LGRP_CONTENT_ALL or
361c6402783Sakolb # LGRP_CONTENT_DIRECT
362c6402783Sakolb void
363c6402783Sakolb lgrp_cpus(cookie, lgrp, content)
364c6402783Sakolb lgrp_cookie_t cookie;
365c6402783Sakolb lgrp_id_t lgrp;
366c6402783Sakolb lgrp_content_t content;
367c6402783Sakolb PREINIT:
368c6402783Sakolb int ncpus;
369c6402783Sakolb processorid_t *cpus;
370c6402783Sakolb PPCODE:
371c6402783Sakolb errno = 0;
372c6402783Sakolb if ((ncpus = lgrp_cpus(cookie, lgrp, NULL, 0, content)) < 0)
373c6402783Sakolb LGRP_BADVAL();
374c6402783Sakolb
375c6402783Sakolb if (GIMME_V == G_SCALAR)
376c6402783Sakolb XSRETURN_IV(ncpus);
377c6402783Sakolb
378c6402783Sakolb if (ncpus > 0) {
379c6402783Sakolb if (New(0, cpus, ncpus, processorid_t) == NULL) {
380c6402783Sakolb errno = ENOMEM;
381c6402783Sakolb LGRP_BADVAL();
382c6402783Sakolb } else {
383c6402783Sakolb ncpus = lgrp_cpus(cookie, lgrp, cpus, ncpus, content);
384c6402783Sakolb PUSHARRAY(cpus, ncpus);
385c6402783Sakolb Safefree(cpus);
386c6402783Sakolb }
387c6402783Sakolb }
388c6402783Sakolb
389c6402783Sakolb void
390c6402783Sakolb lgrp_resources(cookie, lgrp, type)
391c6402783Sakolb lgrp_cookie_t cookie;
392c6402783Sakolb lgrp_id_t lgrp;
393c6402783Sakolb int type;
394c6402783Sakolb PPCODE:
395c6402783Sakolb LGRP_RESOURCES(cookie, lgrp, type);
396