تی‌پاوز (دستور در معماری x86)
تی‌پاوز یا وقفه تی به شکل کاربردی tpause، یک فرمان خاص معماری x86 اینتل است که برای توقف در پردازه از سمت کاربر استفاده می‌شود. با اجرای این دستور، پردازه در حال اجرا برای مدت کوتاهی از به اندازه چند میکروثانیه متوقف می‌شود و پردازنده به حالت ذخیره انرژی می‌رود و انرژی کمتری مصرف می‌کند. این دستور توسط کامپایلر مستقیماً به یک دستور زبان اسمبلی تبدیل می‌شود و فراخوانی سیستم عاملی برای این دستور صورت نمی‌گیرد.
اگر یک پردازه سمت کاربر بخواهد برای مدتی متوقف شود، سازوکارهای زیادی برای آن وجود دارد. یک روش می‌تواند استفاده از دستور sleep باشد؛ بدین ترتیب پردازه برای مدتی از صف اجرای سیستم عامل خارج شده تا زمانی به اندازه زمان مقرر بگذرد تا دوباره توسط زمان‌بند در صف اجرای سیستم عامل قرار بگیرد و دوباره اجرا شود.
مشکل این روش است که یک پردازه را کوتاه‌تر از چند ده میکروثانیه نمی‌توان متوقف کرد. اگر بخواهیم برای مدت کوتاه‌تری یک پردازه را متوقف کنیم، یک روش دیگر استفاده از یک حلقه با بدنهٔ خالی یا همان انتظار مشغول است. مشکل انتظار مشغول این است که انرژی مصرف می‌کند و در عمل کار مفیدی انجام نمی‌دهد. به منظور ارائهٔ یک راه‌حل برای این مسئله، شرکت اینتل دستور tpause را به معماری پردازنده‌های سری اضافه کرده‌است.
این دستور می‌تواند پردازنده را در دو حالت ذخیره‌سازی انرژی ببرد. حالت C0.2 و حالت C0.1. حالت C0.1 ذخیره‌سازی انرژی کمتری نسبت به C0.2 دارد اما خارج شدن از آن حالت سریع است. در مقابل دستور C0.2 قرار دارد که ذخیره‌سازی انرژی آن بیشتر است اما خارج شدن از آن کندتر است.
برای اجرای این دستور اولا باید این ویژگی در پردازنده وجود داشته باشد. به همین منظور می‌توان از کد زیر که در هسته لینوکس نسخه ۵٫۱۲٫۴ در مسیر codice_1 وجود دارد استفاده کرد.
static inline int boot_cpu_has(int flag) unsigned int eax, ebx, ecx, edx;
eax = (flag & 0x100) ? 7 : (flag & 0x20) ? 0x80000001 : 1; ecx = 0;
asm volatile("cpuid"
return ((flag & 0x100 ? ebx : (flag & 0x80) ? ecx : edx) » (flag & 31)) & 1;
int main(int argc, char* argv[]) {
تابع codice_2 یک عدد ورودی می‌گیرد که عدد مشخص‌کننده یک ویژگی خاص در معماری x86 است و یک عدد خروجی می‌دهد. در صورتی که عدد خروجی برابر با ۱ باشد، یعنی آن ویژگی در پردازنده وجود دارد واگر برابر با ۰ باشد، به معنای عدم وجود آن ویژگی است. این عدد برای ویژگی WAITPKG که شامل دستور tpause می‌شود برابر ۵۱۷ است. فهرست اعداد ویژگی‌های معماری را می‌توان در مسیر codice_3 از کد هسته سیستم عامل لینوکس پیدا کرد. با اجرای کد زیر در یک پردازنده حاوی ویژگی WAITPKG، دستور tpause اجرا می‌شود.
unsigned long long rdtsc(void)
int main(int argc, char* argv[]) { unsigned long long now_tsc = rdtsc(); unsigned long long target_tsc = now_tsc + 10000; printf("now in tsc: %llu release time in tsc: %llu\n", now_tsc, target_tsc); _tpause (TPAUSE_C01_STATE, target_tsc);
کد بالا، مقدار شمارندهٔ زمان را از تابع rdtsc می‌گیرد. این شمارنده، تعداد تیک‌های زده شده توسط پردازنده را نشان می‌دهد و همواره با نرخی ثابت اضافه می‌شود. دستور tpause دو عدد می‌گیرد که عدد اول، نشان‌دهندهٔ حالت ذخیره‌سازی انرژی است. این عدد اگر برابر ۱ باشد، معادل حالت C0.2 است وگرنه معادل حالت C0.1 است. ورودی دوم، عددی است که تا رسیدن شمارندهٔ زمان به آن، توقف بایستی ادامه پیدا کند.
tpause خود یک دستور اسمبلی x86 است و بنابراین استفاده از این دستور موجب فراخوانی سیستم عاملی نمی‌شود. بدین ترتیب به نحوی سیستم عامل باید کنترلی روی اجرای این دستور داشته باشد و یک پردازه نتواند بیشتر از یک مقدار ثابت در پردازه و بدون این که اجازهٔ اجرا را به پردازهٔ دیگری بدهد، متوقف شود. همچنین، ممکن است بخواهیم که پردازنده اجازهٔ وارد شدن به حالت C0.2 را نداشته باشد.
به همین منظور، سیستم عامل می‌تواند حداکثر زمانی را که یک پردازه می‌تواند در این حالت قرار بگیرد، بر حسب واحد شمارندهٔ زمان () در ثبات خاص منظوره codice_4 بنویسد. همچنین، اگر سیستم عامل در این ثبات در بیت ابتدایی مقدار صفر بنویسد، برنامه‌های سمت کاربر نمی‌توانند وارد حالت ذخیره‌سازی C0.2 شوند و اگر چنین درخواستی داشته باشند، همان درخواست در حالت C0.1 برای آن‌ها اجرا می‌شود.