1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 
30 #include <stdlib.h>
31 #include <sys/lgrp_user.h>
32 
33 #include "jlgrp.h"
34 
35 static lgrp_cookie_t getCookie(JNIEnv *, jclass, jobject);
36 static void throwException(JNIEnv *, const char *, const char *);
37 
38 /*
39  * Return the output of the getCookie() method executed on the
40  * supplied instance.
41  */
42 lgrp_cookie_t
43 getCookie(JNIEnv *env, jclass clazz, jobject obj)
44 {
45 	jfieldID fid;
46 
47 	fid = (*env)->GetFieldID(env, clazz, "cookie", "J");
48 	return ((lgrp_cookie_t)(*env)->GetLongField(env, obj, fid));
49 }
50 
51 /*
52  * Throw an exception of the specified class with the specified message.
53  */
54 void
55 throwException(JNIEnv *env, const char *class, const char *msg)
56 {
57 	jclass clazz;
58 
59 	clazz = (*env)->FindClass(env, class);
60 
61 	(*env)->ThrowNew(env, clazz, msg);
62 }
63 
64 /*
65  * Obtain an lgrp cookie for an lgrp snapshot which contains details
66  * about available resources that the operating system knows about.
67  *
68  * If the call fails, then throw an exception which indicates that the
69  * snapshot could not be obtained.
70  */
71 /*ARGSUSED1*/
72 JNIEXPORT jlong JNICALL
73 Java_com_sun_solaris_service_locality_LocalityDomain_jl_1init(JNIEnv *env,
74     jobject obj, jint view)
75 {
76 	lgrp_cookie_t cookie;
77 
78 	if ((cookie = lgrp_init(view)) == LGRP_COOKIE_NONE) {
79 		throwException(env, "java/lang/Exception",
80 		    "Could not obtain latency group cookie");
81 	}
82 
83 	return ((jlong)cookie);
84 }
85 
86 /*
87  * Release the snapshot in use by this instance. It is assumed that
88  * the cookie is held in the "cookie" field of the invoking instance
89  */
90 JNIEXPORT jint JNICALL
91 Java_com_sun_solaris_service_locality_LocalityDomain_jl_1fini(JNIEnv *env,
92     jobject obj)
93 {
94 	jclass clazz;
95 
96 	clazz = (*env)->GetObjectClass(env, obj);
97 	return ((jint)lgrp_fini(getCookie(env, clazz, obj)));
98 }
99 
100 /*
101  * Create a new LocalityGroup object which acts as a proxy for the
102  * root LocalityGroup.
103  */
104 JNIEXPORT jobject JNICALL
105 Java_com_sun_solaris_service_locality_LocalityDomain_jl_1root(JNIEnv *env,
106     jobject obj)
107 {
108 	jclass clazz;
109 	jmethodID mid;
110 	jlong root;
111 	jobject lgrp;
112 
113 	clazz = (*env)->GetObjectClass(env, obj);
114 
115 	root = (jlong) lgrp_root(getCookie(env, clazz, obj));
116 
117 	clazz = (*env)->FindClass(env, "com/sun/solaris/service/locality/"
118 	    "LocalityGroup");
119 	mid = (*env)->GetMethodID(env, clazz, "<init>", "(Lcom/sun/solaris/"
120 	    "service/locality/LocalityDomain;JLcom/sun/solaris/service/"
121 	    "locality/LocalityGroup;)V");
122 	lgrp = (*env)->NewObject(env, clazz, mid, obj, root, NULL);
123 	return (lgrp);
124 }
125 
126 /*
127  * Return a new array containing all of the child LocalityGroup ids
128  * for the supplied instance.
129  */
130 JNIEXPORT jlongArray JNICALL
131 Java_com_sun_solaris_service_locality_LocalityGroup_jl_1children(JNIEnv *env,
132     jobject obj)
133 {
134 	jclass clazz;
135 	jfieldID fid;
136 	lgrp_cookie_t cookie;
137 	jlong id;
138 	jsize nchild0, nchild;
139 	jlongArray children;
140 	int i;
141 	lgrp_id_t *native_child;
142 	jlong *java_child;
143 	jobject domain;
144 
145 	clazz = (*env)->GetObjectClass(env, obj);
146 	fid = (*env)->GetFieldID(env, clazz, "domain",
147 	    "Lcom/sun/solaris/service/locality/LocalityDomain;");
148 	domain = (*env)->GetObjectField(env, obj, fid);
149 
150 	cookie = getCookie(env, (*env)->GetObjectClass(env, domain), domain);
151 	fid = (*env)->GetFieldID(env, clazz, "id", "J");
152 	id = (*env)->GetLongField(env, obj, fid);
153 retry:
154 	nchild0 = (jsize)lgrp_children(cookie, (lgrp_id_t)id, NULL, 0);
155 	children = (*env)->NewLongArray(env, nchild0);
156 	if ((native_child = calloc(nchild0, sizeof (lgrp_id_t))) == NULL) {
157 		throwException(env, "java/lang/Exception",
158 		    "Could not allocate memory for native_child array");
159 		return (NULL);
160 	}
161 	nchild = lgrp_children(cookie, (lgrp_id_t)id, native_child, nchild0);
162 	if (nchild != nchild0) {
163 		free(native_child);
164 		goto retry;
165 	}
166 
167 	if ((java_child = calloc(nchild, sizeof (jlong))) == NULL) {
168 		throwException(env, "java/lang/Exception",
169 		    "Could not allocate memory for java_child array");
170 		free(native_child);
171 		return (NULL);
172 	}
173 
174 	for (i = 0; i < nchild; i++)
175 		java_child[i] = (jlong) native_child[i];
176 	(*env)->SetLongArrayRegion(env, children, 0, nchild, java_child);
177 	free(native_child);
178 	free(java_child);
179 	return (children);
180 }
181 
182 /*
183  * Return a new array containing all of the cpus contained directly
184  * within the LocalityGroup identified by the supplied instance.
185  */
186 JNIEXPORT jintArray JNICALL
187 Java_com_sun_solaris_service_locality_LocalityGroup_jl_1cpus(JNIEnv *env,
188     jobject obj)
189 {
190 	jclass clazz;
191 	jfieldID fid;
192 	lgrp_cookie_t cookie;
193 	jlong id;
194 	jsize ncpus0, ncpus;
195 	jintArray cpus;
196 	int i;
197 	processorid_t *native_cpus;
198 	jint *java_cpus;
199 	jobject domain;
200 
201 	clazz = (*env)->GetObjectClass(env, obj);
202 	fid = (*env)->GetFieldID(env, clazz, "domain",
203 	    "Lcom/sun/solaris/service/locality/LocalityDomain;");
204 	domain = (*env)->GetObjectField(env, obj, fid);
205 
206 	cookie = getCookie(env, (*env)->GetObjectClass(env, domain), domain);
207 
208 	fid = (*env)->GetFieldID(env, clazz, "id", "J");
209 	id = (*env)->GetLongField(env, obj, fid);
210 retry:
211 	ncpus0 = (jsize)lgrp_cpus((lgrp_cookie_t)cookie, (lgrp_id_t)id,
212 	    NULL, 0, LGRP_CONTENT_DIRECT);
213 	cpus = (*env)->NewIntArray(env, ncpus0);
214 	if ((native_cpus = calloc(ncpus0, sizeof (processorid_t))) == NULL) {
215 		throwException(env, "java/lang/Exception",
216 		    "Could not allocate memory for native_cpus array");
217 		return (NULL);
218 	}
219 	ncpus = (jsize)lgrp_cpus((lgrp_cookie_t)cookie, (lgrp_id_t)id,
220 	    native_cpus, ncpus0, LGRP_CONTENT_DIRECT);
221 	if (ncpus != ncpus0) {
222 		free(native_cpus);
223 		goto retry;
224 	}
225 
226 	if ((java_cpus = calloc(ncpus, sizeof (jint))) == NULL) {
227 		free(native_cpus);
228 		throwException(env, "java/lang/Exception",
229 		    "Could not allocate memory for java_cpus array");
230 		return (NULL);
231 	}
232 
233 	for (i = 0; i < ncpus; i++)
234 		java_cpus[i] = (jint)native_cpus[i];
235 	(*env)->SetIntArrayRegion(env, cpus, 0, ncpus, java_cpus);
236 	free(native_cpus);
237 	free(java_cpus);
238 	return (cpus);
239 }
240 
241 /*
242  * Return the latency between two supplied latency group IDs.
243  */
244 /*ARGSUSED*/
245 JNIEXPORT jint JNICALL
246 Java_com_sun_solaris_service_locality_LocalityGroup_jl_1latency(JNIEnv *env,
247     jobject obj, jlong from, jlong to)
248 {
249 	return ((jint) lgrp_latency((lgrp_id_t)from, (lgrp_id_t)to));
250 }
251