This repository has been archived by the owner on Jun 18, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: David Vernet <[email protected]>
- Loading branch information
Showing
3 changed files
with
210 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
#include <errno.h> | ||
#include <libgen.h> | ||
#include <pthread.h> | ||
#include <sched.h> | ||
#include <signal.h> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <stdint.h> | ||
#include <string.h> | ||
#include <unistd.h> | ||
|
||
#define MIN_NICENESS -20 | ||
#define MAX_NICENESS 19 | ||
static int niceness = MIN_NICENESS; | ||
|
||
#define MAX_THREADS 1024 | ||
|
||
static const char help_fmt[] = | ||
"A helper for creating infeasible weight conditions.\n" | ||
"\n" | ||
"Usage: %s [-n NICENESS] [-t NTASKS] [-h]\n" | ||
"\n" | ||
" -n NICENESS The niceness value to use for each thread. Must be in [-20, 19].\n" | ||
" -t NTASKS The number of tasks to create. Must not exceed 1024.\n" | ||
" -h Display this help and exit\n"; | ||
|
||
|
||
static volatile int done = 0; | ||
|
||
static void handle_sigint(int sig) | ||
{ | ||
done = 1; | ||
} | ||
|
||
static void *busy_spin(void *ctx) | ||
{ | ||
uint64_t value = 0; | ||
pid_t pid = getpid(); | ||
pthread_t tid = pthread_self(); | ||
|
||
if (!nice(niceness) && errno != 0) { | ||
fprintf(stderr, "Failure: (%s)\n", strerror(errno)); | ||
done = 1; | ||
return NULL; | ||
} | ||
|
||
while (!done) { | ||
value++; | ||
if (value % 10000 == 0) { | ||
printf("%d[%lu] nice= %d\n", | ||
pid, tid, nice(0)); | ||
} | ||
} | ||
|
||
return NULL; | ||
} | ||
|
||
int main(int argc, char **argv) | ||
{ | ||
unsigned num_threads = 1, i; | ||
pthread_t tids[MAX_THREADS]; | ||
int opt; | ||
|
||
signal(SIGINT, handle_sigint); | ||
signal(SIGTERM, handle_sigint); | ||
|
||
while ((opt = getopt(argc, argv, "n:t:h")) != -1) { | ||
switch (opt) { | ||
case 'n': | ||
niceness = strtol(optarg, NULL, 10); | ||
break; | ||
case 't': | ||
num_threads = strtol(optarg, NULL, 10); | ||
break; | ||
default: | ||
fprintf(stderr, help_fmt, basename(argv[0])); | ||
return opt != 'h'; | ||
} | ||
} | ||
|
||
if (niceness < MIN_NICENESS || niceness > MAX_NICENESS) { | ||
fprintf(stderr, "Invalid niceness %d, must be in [%d, %d]\n", | ||
niceness, MIN_NICENESS, MAX_NICENESS); | ||
fprintf(stderr, help_fmt, basename(argv[0])); | ||
return 1; | ||
} | ||
|
||
if (num_threads >= MAX_THREADS) { | ||
fprintf(stderr, "%u exceeds max threads %u\n", num_threads, | ||
MAX_THREADS); | ||
fprintf(stderr, help_fmt, basename(argv[0])); | ||
return 1; | ||
} | ||
|
||
for (i = 0; i < num_threads; i++) { | ||
if (pthread_create(&tids[i], NULL, busy_spin, NULL)) { | ||
fprintf(stderr, "Failed to create thread %u\n", i); | ||
return 1; | ||
} | ||
} | ||
|
||
for (i = 0; i < num_threads; i++) | ||
pthread_join(tids[i], NULL); | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
#!/bin/bash | ||
# SPDX-License-Identifier: GPL-2.0 | ||
# Copyright (C) 2024 David Vernet <[email protected]> | ||
# Copyright (C) 2024 Meta Platforms, Inc. and affiliates. | ||
|
||
# Script to make a cgroup with conditions that should cause the infeasible | ||
# weight problem to manifest | ||
|
||
INFEASIBLE_CGRP_ROOT="/sys/fs/cgroup/infeasible.scope" | ||
|
||
function cgrp_n_tasks() { | ||
return "${curr_pids}" | ||
} | ||
|
||
# create_cgrp() - Create the root infeasible cgroup | ||
function create_cgrp() { | ||
local weight=10000 | ||
|
||
if [[ ! -d "${INFEASIBLE_CGRP_ROOT}" ]]; then | ||
mkdir "${INFEASIBLE_CGRP_ROOT}" | ||
echo "created root infeasible group ${INFEASIBLE_CGRP_ROOT}" | ||
else | ||
echo "root infeasible group ${INFEASIBLE_CGRP_ROOT} already existed" | ||
local curr_pids=$(cat "${INFEASIBLE_CGRP_ROOT}/pids.current") | ||
if [ "${curr_pids}" != "0" ]; then | ||
echo "ERR: tasks found in ${INFEASIBLE_CGRP_ROOT}" | ||
exit 1 | ||
fi | ||
fi | ||
|
||
echo "setting ${INFEASIBLE_CGRP_ROOT} weight to ${weight}" | ||
echo ${weight} > "${INFEASIBLE_CGRP_ROOT}/cpu.weight" | ||
echo "set ${INFEASIBLE_CGRP_ROOT} weight to ${weight}" | ||
} | ||
|
||
# spawn_tasks(ntasks) - Spawn tasks with low niceness and return the pid | ||
function spawn_tasks() { | ||
local ntasks=$1 | ||
|
||
if [ -z $ntasks ]; then | ||
ntasks=$(($(nproc)/4)) | ||
fi | ||
echo "spawning ${ntasks} tasks" | ||
./highpri -t ${ntasks} > /tmp/highpri.out 2> /tmp/highpri.err & | ||
local status=$? | ||
echo "status was: ${status}" | ||
pid=$! | ||
echo "pid is ${pid}" | ||
echo "spawned highpri task ${pid}" | ||
if [ ${pid} -le 0 ]; then | ||
echo "ERR: failed to spawned highpri tasks" | ||
exit 1 | ||
fi | ||
} | ||
|
||
# Move the tasks into the infeasible cgroup | ||
function move_into_cgrp() { | ||
local pid=$1 | ||
local procsfile="${INFEASIBLE_CGRP_ROOT}/cgroup.procs" | ||
local pidsfile="${INFEASIBLE_CGRP_ROOT}/pids.current" | ||
|
||
echo "moving ${pid} into ${procsfile}" | ||
echo " procs in before: $(cat ${pidsfile})" | ||
echo "${pid}" >> "${procsfile}" | ||
local status=$? | ||
echo "status was: ${status}" | ||
if [ ${status} -ne 0 ]; then | ||
echo "ERR: failed to move ${pid} into ${procsfile}" | ||
echo "ERR: destroying ${pid}" | ||
kill -9 ${pid} | ||
echo "ERR: killed ${pid}. waiting for exit..." | ||
wait | ||
echo "ERR: ${pid} exited" | ||
exit 1 | ||
fi | ||
echo " procs in after: $(cat ${pidsfile})" | ||
} | ||
|
||
function cleanup() { | ||
local curr_pids=$(cat "${INFEASIBLE_CGRP_ROOT}/pids.current") | ||
if [ "${curr_pids}" != "0" ]; then | ||
echo "WARN: ${curr_pids} tasks remaining in ${INFEASIBLE_CGRP_ROOT}" | ||
fi | ||
} | ||
|
||
function _term() { | ||
echo "Caught SIGINT signal" | ||
kill -s SIGINT "${pid}" | ||
} | ||
|
||
create_cgrp | ||
pid="" | ||
trap _term SIGINT | ||
spawn_tasks | ||
move_into_cgrp ${pid} | ||
echo "success: waiting for ${pid} to finish" | ||
wait ${pid} | ||
echo "${pid} exited. cleaning up..." | ||
cleanup |