July 25, 2009
POSIX thread priority and policy handling in Common Lisp
The POSIX threads interface allows user applications to manage scheduling policies and priorities. Certain threads can be made to wait in favor of other threads (priority), and the order of execution for threads of equal priority can be specified (policy).
Below is a humble example interface to access this API.
(asdf:oos 'asdf:load-op 'cffi) (defpackage :prio (:use :cl :cffi)) (in-package :prio) ;;; constants ;; CFFI-GROVEL offers a more reliable solution for this, ;; but let's keep it simple. (defconstant +sched_other+ 0) (defconstant +sched_fifo+ 1) (defconstant +sched_rr+ 2) ;;; define the pthread library (define-foreign-library libpthread (:unix "libpthread.so.0")) (use-foreign-library libpthread) ;;; C structures and functions (defcstruct sched_param (sched_priority :int)) (defcfun "pthread_getschedparam" :int (thread :pointer) (policy (:pointer :int)) (param (:pointer sched_param))) (defcfun "pthread_setschedparam" :int (thread :pointer) (policy :int) (param (:pointer sched_param))) ;;; Lisp interface (defun get-thread-policy-and-priority (thread) (with-foreign-object (policy-ptr :int) (with-foreign-object (param-ptr 'sched_param) (let* ((result (pthread-getschedparam (make-pointer (sb-thread::thread-os-thread thread)) policy-ptr param-ptr)) (policy (mem-ref policy-ptr :int)) (prio (foreign-slot-value param-ptr 'sched_param 'sched_priority))) (declare (fixnum prio policy)) (values policy prio result))))) (defun set-thread-policy-and-priority (thread policy priority) (with-foreign-object (param-ptr 'sched_param) (setf (foreign-slot-value param-ptr 'sched_param 'sched_priority) priority) (let ((result (pthread-setschedparam (make-pointer (sb-thread::thread-os-thread thread)) policy param-ptr))) (declare (fixnum result)) result))) ;;; test (format t "~A~%" (multiple-value-list (get-thread-policy-and-priority sb-thread:*current-thread*))) (format t "~A~%" (set-thread-policy-and-priority sb-thread:*current-thread* +sched_fifo+ 5)) (format t "~A~%" (multiple-value-list (get-thread-policy-and-priority sb-thread:*current-thread*)))
This is by no means a comprehensive solution. In particular POSIX only guarantees a minimum 32 distinct priority values, and the SCHED_OTHER policy doesn’t support non-zero priorities at all. As pointed out in sched_setscheduler(2) (man page for the Linux implementation of sched_setscheduler) the functions sched_get_priority_min and sched_get_priority_max should be used to check the priority range supported by a policy.
You will also note the tiny SBCL-specific bits. To port this to other implementations that use pthreads you need to find out how to get the pointer to the thread’s underlying pthread_t object.