1/* Copyright (c) 2007-2009, Stanford University
2* All rights reserved.
3*
4* Redistribution and use in source and binary forms, with or without
5* modification, are permitted provided that the following conditions are met:
6*     * Redistributions of source code must retain the above copyright
7*       notice, this list of conditions and the following disclaimer.
8*     * Redistributions in binary form must reproduce the above copyright
9*       notice, this list of conditions and the following disclaimer in the
10*       documentation and/or other materials provided with the distribution.
11*     * Neither the name of Stanford University nor the names of its
12*       contributors may be used to endorse or promote products derived from
13*       this software without specific prior written permission.
14*
15* THIS SOFTWARE IS PROVIDED BY STANFORD UNIVERSITY ``AS IS'' AND ANY
16* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18* DISCLAIMED. IN NO EVENT SHALL STANFORD UNIVERSITY BE LIABLE FOR ANY
19* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25*/
26
27/* OS specific headers and defines. */
28#ifdef _LINUX_
29#define _GNU_SOURCE
30#include <sched.h>
31
32#elif defined (_SOLARIS_)
33#include <sys/procset.h>
34#include <sys/processor.h>
35#include <sys/lgrp_user.h>
36
37#elif defined (BARRELFISH)
38#else
39#error OS not supported
40#endif
41
42#include <stdlib.h>
43#include <sys/types.h>
44#include <assert.h>
45
46#include "processor.h"
47#include "memory.h"
48
49int num_cpus = 2;
50
51/* Query the number of CPUs online. */
52int proc_get_num_cpus (void)
53{
54    return num_cpus;
55
56    /* int num_cpus; */
57    /* char *num_proc_str; */
58
59    /* num_cpus = sysconf(_SC_NPROCESSORS_ONLN); */
60
61    /* /\* Check if the user specified a different number of processors. *\/ */
62    /* if ((num_proc_str = getenv("MAPRED_NPROCESSORS"))) */
63    /* { */
64    /*     int temp = atoi(num_proc_str); */
65    /*     if (temp < 1 || temp > num_cpus) */
66    /*         num_cpus = 0; */
67    /*     else */
68    /*         num_cpus = temp; */
69    /* } */
70
71    /* return num_cpus; */
72}
73
74#ifdef _LINUX_
75static cpu_set_t    full_cs;
76static cpu_set_t* proc_get_full_set(void)
77{
78    static int          inited = 0;
79
80    if (inited == 0) {
81        int i;
82        int n_cpus;
83
84        CPU_ZERO (&full_cs);
85        n_cpus = sysconf(_SC_NPROCESSORS_ONLN);
86        for (i = 0; i < n_cpus; i++) {
87            CPU_SET(i, &full_cs);
88        }
89
90        inited = 1;
91    }
92
93    return &full_cs;
94}
95#endif
96
97/* Bind the calling thread to run on CPU_ID.
98   Returns 0 if successful, -1 if failed. */
99int proc_bind_thread (int cpu_id)
100{
101#ifdef _LINUX_
102    cpu_set_t   cpu_set;
103
104    CPU_ZERO (&cpu_set);
105    CPU_SET (cpu_id, &cpu_set);
106
107    return sched_setaffinity (0, sizeof (cpu_set), &cpu_set);
108#elif defined (_SOLARIS_)
109    return processor_bind (P_LWPID, P_MYID, cpu_id, NULL);
110#elif defined (BARRELFISH)
111    return 0;
112#endif
113}
114
115int proc_unbind_thread ()
116{
117#ifdef _LINUX_
118    return sched_setaffinity (0, sizeof (cpu_set_t), proc_get_full_set());
119#elif defined (_SOLARIS_)
120    return processor_bind (P_LWPID, P_MYID, PBIND_NONE, NULL);
121#elif defined (BARRELFISH)
122    return 0;
123#endif
124}
125
126/* Test whether processor CPU_ID is available. */
127bool proc_is_available (int cpu_id)
128{
129#ifdef _LINUX_
130    int ret;
131    cpu_set_t cpu_set;
132
133    ret = sched_getaffinity (0, sizeof (cpu_set), &cpu_set);
134    if (ret < 0) return false;
135
136    return CPU_ISSET (cpu_id, &cpu_set) ? true : false;
137#elif defined (_SOLARIS_)
138    return (p_online (cpu_id, P_STATUS) == P_ONLINE);
139#elif defined (BARRELFISH)
140    return true;
141#endif
142}
143
144int proc_get_cpuid (void)
145{
146#ifdef _LINUX_
147    int i, ret;
148    cpu_set_t cpu_set;
149
150    ret = sched_getaffinity (0, sizeof (cpu_set), &cpu_set);
151    if (ret < 0) return -1;
152
153    for (i = 0; i < CPU_SETSIZE; ++i)
154    {
155        if (CPU_ISSET (i, &cpu_set)) break;
156    }
157    return i;
158#elif defined (_SOLARIS_)
159    return getcpuid ();
160#elif defined (BARRELFISH)
161    return disp_get_core_id();
162#endif
163}
164