/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2016, Joyent, Inc.
*/
#include <sys/ipc_impl.h>
#include <sys/port_kernel.h>
/*
* Dummy structure used when comparing projects. This structure must be kept
* identical to the first two fields of kproject_t.
*/
struct project_zone {
};
/*
* Projects
*
* A dictionary of all active projects is maintained by the kernel so that we
* may track project usage and limits. (By an active project, we mean a
* project associated with one or more task, and therefore with one or more
* processes.) We build the dictionary on top of the mod_hash facility, since
* project additions and deletions are relatively rare events. An
* integer-to-pointer mapping is maintained within the hash, representing the
* map from project id to project structure. All projects, including the
* primordial "project 0", are allocated via the project_hold_by_id()
* interface.
*
* Currently, the project contains a reference count; the project ID, which is
* examined by the extended accounting subsystem as well as /proc; a resource
* control set, which contains the allowable values (and actions on exceeding
* those values) for controlled project-level resources on the system; and a
* number of CPU shares, which is used by the fair share scheduling class
* (FSS) to support its proportion-based scheduling algorithm.
*
* Reference counting convention
* The dictionary entry does not itself count as a reference--only references
* outside of the subsystem are tallied. At the drop of the final external
* reference, the project entry is removed. The reference counter keeps
* track of the number of threads *and* tasks within a project.
*
* Locking
* Walking the doubly-linked project list must be done while holding
* projects_list_lock. Thus, any dereference of kpj_next or kpj_prev must be
* under projects_list_lock.
*
* If both the hash lock, project_hash_lock, and the list lock are to be
* acquired, the hash lock is to be acquired first.
*/
static void
{
/*
* Initialize subsystem-specific data
*/
data->kpd_shmmax = 0;
data->kpd_locked_mem = 0;
data->kpd_contract = 0;
data->kpd_crypto_mem = 0;
}
/*ARGSUSED*/
static uint_t
{
/*
* Merge the zoneid and projectid together to a 32-bit quantity, and
* then pass that in to the existing idhash.
*/
}
static int
{
int retval;
}
static void
{
}
/*
* kproject_t *project_hold(kproject_t *)
*
* Overview
* Record that an additional reference on the indicated project has been
* taken.
*
* Return values
* A pointer to the indicated project.
*
* Caller's context
* project_hash_lock must not be held across the project_hold() call.
*/
{
p->kpj_count++;
return (p);
}
/*
* kproject_t *project_hold_by_id(projid_t, zone_t *, int)
*
* Overview
* project_hold_by_id() performs a look-up in the dictionary of projects
* active on the system by specified project ID + zone and puts a hold on
* it. The third argument defines the desired behavior in the case when
* project with given project ID cannot be found:
*
* PROJECT_HOLD_INSERT New entry is made in dictionary and the project
* is added to the global list.
*
* PROJECT_HOLD_FIND Return NULL.
*
* The project is returned with its reference count incremented by one.
* A new project derives its resource controls from those of project 0.
*
* Return values
* A pointer to the held project.
*
* Caller's context
* Caller must be in a context suitable for KM_SLEEP allocations.
*/
{
kproject_t *p;
if (flag == PROJECT_HOLD_FIND) {
(mod_hash_val_t)&p) == MH_ERR_NOTFOUND)
p = NULL;
else
p->kpj_count++;
return (p);
}
set = rctl_set_create();
(mod_hash_val_t *)&p) == MH_ERR_NOTFOUND) {
p = spare_p;
p->kpj_count = 0;
p->kpj_shares = 1;
p->kpj_nlwps = 0;
p->kpj_nprocs = 0;
p->kpj_ntasks = 0;
p->kpj_nlwps_ctl = INT_MAX;
p->kpj_nprocs_ctl = INT_MAX;
p->kpj_ntasks_ctl = INT_MAX;
project_data_init(&p->kpj_data);
e.rcep_t = RCENTITY_PROJECT;
(mod_hash_val_t)p, hndl))
/*
* Insert project into global project list.
*/
p->kpj_next = projects_list;
projects_list->kpj_prev = p;
} else {
/*
* Special case: primordial hold on project 0.
*/
p->kpj_next = p;
p->kpj_prev = p;
projects_list = p;
}
} else {
}
p->kpj_count++;
/*
* The kstat stores the project's zone name, as zoneid's may change
* across reboots.
*/
/*
* Inform CPU caps framework of the new project
*/
/*
* Set up project kstats
*/
project_kstat_create(p, zone);
}
return (p);
}
/*
* void project_rele(kproject_t *)
*
* Overview
* Advertise that one external reference to this project is no longer needed.
*
* Return values
* None.
*
* Caller's context
* No restriction on context.
*/
void
{
p->kpj_count--;
if (p->kpj_count == 0) {
/*
* Remove project from global list.
*/
ASSERT(p->kpj_nprocs == 0);
if (projects_list == p)
projects_list = p->kpj_next;
rctl_set_free(p->kpj_rctls);
klpd_freelist(&p->kpj_klpd);
p->kpj_zoneid);
}
}
/*
* int project_walk_all(zoneid_t, int (*)(kproject_t *, void *), void *)
*
* Overview
* Walk the project list for the given zoneid with a callback.
*
* Return values
* -1 for an invalid walk, number of projects visited otherwise.
*
* Caller's context
* projects_list_lock must not be held, as it is acquired by
* project_walk_all(). Accordingly, callbacks may not perform KM_SLEEP
* allocations.
*/
int
void *walk_data)
{
int cnt = 0;
do {
continue;
cnt = -1;
break;
} else {
cnt++;
}
return (cnt);
}
/*
* projid_t curprojid(void)
*
* Overview
* Return project ID of the current thread
*
* Caller's context
* No restrictions.
*/
{
}
/*
* project.cpu-shares resource control support.
*/
/*ARGSUSED*/
static rctl_qty_t
{
}
/*ARGSUSED*/
static int
{
return (0);
return (0);
}
};
/*
* project.cpu-cap resource control support.
*/
/*ARGSUSED*/
static rctl_qty_t
{
}
/*ARGSUSED*/
static int
{
return (0);
/*
* set cap to the new value.
*/
}
};
/*ARGSUSED*/
static rctl_qty_t
{
return (nlwps);
}
/*ARGSUSED*/
static int
{
return (0);
return (1);
return (0);
}
/*ARGSUSED*/
static int
rctl_qty_t nv) {
return (0);
return (0);
}
};
/*ARGSUSED*/
static rctl_qty_t
{
return (nprocs);
}
/*ARGSUSED*/
static int
{
return (0);
return (1);
return (0);
}
/*ARGSUSED*/
static int
rctl_qty_t nv) {
return (0);
return (0);
}
};
/*ARGSUSED*/
static rctl_qty_t
{
return (ntasks);
}
/*ARGSUSED*/
static int
{
return (1);
return (0);
}
/*ARGSUSED*/
static int
rctl_qty_t nv) {
return (0);
}
};
/*
* project.max-shm-memory resource control support.
*/
/*ARGSUSED*/
static rctl_qty_t
{
}
/*ARGSUSED*/
static int
{
rctl_qty_t v;
return (1);
return (0);
}
};
/*
* project.max-shm-ids resource control support.
*/
/*ARGSUSED*/
static rctl_qty_t
{
}
/*ARGSUSED*/
static int
{
rctl_qty_t v;
return (1);
return (0);
}
};
/*
* project.max-sem-ids resource control support.
*/
/*ARGSUSED*/
static rctl_qty_t
{
}
/*ARGSUSED*/
static int
{
rctl_qty_t v;
return (1);
return (0);
}
};
/*
* project.max-msg-ids resource control support.
*/
/*ARGSUSED*/
static rctl_qty_t
{
}
/*ARGSUSED*/
static int
{
rctl_qty_t v;
return (1);
return (0);
}
};
/*ARGSUSED*/
static rctl_qty_t
{
rctl_qty_t q;
return (q);
}
/*ARGSUSED*/
static int
{
rctl_qty_t q;
return (1);
return (0);
}
/*ARGSUSED*/
static int
rctl_qty_t nv) {
return (0);
return (0);
}
};
/*
* project.max-contracts resource control support.
*/
/*ARGSUSED*/
static int
{
rctl_qty_t v;
return (1);
return (0);
}
};
/*ARGSUSED*/
static rctl_qty_t
{
}
/*ARGSUSED*/
static int
{
return (0);
return (0);
}
/*ARGSUSED*/
static int
{
rctl_qty_t v;
return (1);
return (0);
}
};
/*
* void project_init(void)
*
* Overview
* Initialize the project subsystem, including the primordial project 0 entry.
* Register generic project resource controls, if any.
*
* Return values
* None.
*
* Caller's context
* Safe for KM_SLEEP allocations.
*/
void
project_init(void)
{
/*
* currently don't allow modules to be unloaded, and the control
* must be registered before init starts.
*/
/*
* Default to a quarter of the machine's memory
*/
/*
* System V IPC resource controls
*/
shmmni = 100;
else
shmmax = 0x800000;
else
/*
* Default to a quarter of the machine's memory
*/
if (check) {
qty = UINT64_MAX;
}
/*
* Event Ports resource controls
*/
/*
* Resource control for locked memory
*/
"project.max-locked-memory", RCENTITY_PROJECT,
/*
* Per project limit on contracts.
*/
}
static int
{
if (rw == KSTAT_WRITE)
return (EACCES);
return (0);
}
static int
{
if (rw == KSTAT_WRITE)
return (EACCES);
return (0);
}
static kstat_t *
int (*updatefunc) (kstat_t *, int))
{
sizeof (kproject_kstat_t) / sizeof (kstat_named_t),
return (NULL);
return (ksp);
}
static void
{
}
static void
{
void *data;
}
}
static void
{
}