netdev = hr_dev->iboe.netdevs[port];
if (!netdev) {
dev_err(dev, "port(%d) can't find netdev\n", port);
return -ENODEV;
spin_lock_bh(&hr_dev->iboe.lock);
switch (event) {
case NETDEV_UP:
case NETDEV_CHANGE:
case NETDEV_REGISTER:
case NETDEV_CHANGEADDR:
hns_roce_set_mac(hr_dev, port, netdev->dev_addr);
break;
case NETDEV_DOWN:
* In v1 engine, only support all ports closed together.
break;
default:
dev_dbg(dev, "NETDEV event = 0x%x!\n", (u32)(event));
break;
spin_unlock_bh(&hr_dev->iboe.lock);
return 0;
这段code中在spin_lock_bh/spin_unlock_bh 之间调用hns_roce_set_mac,而hns_roce_set_mac->hns_roce_set_mac->hns_roce_v1_set_mac
void hns_roce_v1_set_mac(struct hns_roce_dev *hr_dev, u8 phy_port, u8 *addr)
u32 reg_smac_l;
u16 reg_smac_h;
u16 *p_h;
u32 *p;
u32 val;
* When mac changed, loopback may fail
* because of smac not equal to dmac.
* We Need to release and create reserved qp again.
if (hr_dev->hw->dereg_mr && hns_roce_v1_recreate_lp_qp(hr_dev))
dev_warn(&hr_dev->pdev->dev, "recreate lp qp timeout!\n");
hns_roce_v1_set_mac 中又会调用hns_roce_v1_recreate_lp_qp
static int hns_roce_v1_recreate_lp_qp(struct hns_roce_dev *hr_dev)
struct device *dev = &hr_dev->pdev->dev;
struct hns_roce_recreate_lp_qp_work *lp_qp_work;
struct hns_roce_free_mr *free_mr;
struct hns_roce_v1_priv *priv;
struct completion comp;
unsigned long end =
msecs_to_jiffies(HNS_ROCE_V1_RECREATE_LP_QP_TIMEOUT_MSECS) + jiffies;
while (time_before_eq(jiffies, end)) {
if (try_wait_for_completion(&comp))
return 0;
msleep(HNS_ROCE_V1_RECREATE_LP_QP_WAIT_VALUE);
在hns_roce_v1_recreate_lp_qp 中调用msleep函数,就违反了不能在atomic环境中sleep的情况,这样在
__schedule->schedule_debug
static inline void schedule_debug(struct task_struct *prev)
#ifdef CONFIG_SCHED_STACK_END_CHECK
if (task_stack_end_corrupted(prev))
panic("corrupted stack end detected inside scheduler\n");
#endif
//这个条件就会符合,所以调用__schedule_bug
if (unlikely(in_atomic_preempt_off())) {
__schedule_bug(prev);
preempt_count_set(PREEMPT_DISABLED);
rcu_sleep_check();
profile_hit(SCHED_PROFILING, __builtin_return_address(0));
schedstat_inc(this_rq()->sched_count);
static noinline void __schedule_bug(struct task_struct *prev)
/* Save this before calling printk(), since that will clobber it */
unsigned long preempt_disable_ip = get_preempt_disable_ip(current);
if (oops_in_progress)
return;
printk(KERN_ERR "BUG: scheduling while atomic: %s/%d/0x%08x\n",
prev->comm, prev->pid, preempt_count());
这样就会打印BUG: scheduling while atomic 这样的log。并出给当前京进程的name和pid。
而#define in_atomic_preempt_off() (preempt_count() != PREEMPT_DISABLE_OFFSET)
可见就是就是检测preempt_count是否等于PREEMPT_DISABLE_OFFSET==0.不为0也就是说当前是原子环境
那么为啥spin_lock_bh/spin_unlock_bh 之间的环境是原子环境呢?
static __always_inline void spin_lock_bh(spinlock_t *lock)
raw_spin_lock_bh(&lock->rlock);
#define raw_spin_lock_bh(lock) _raw_spin_lock_bh(lock)
void __lockfunc _raw_spin_lock_bh(raw_spinlock_t *lock)
__raw_spin_lock_bh(lock);
static inline void __raw_spin_lock_irq(raw_spinlock_t *lock)
local_irq_disable();
preempt_disable();
spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);
重点是调用preempt_disable
#define preempt_disable() \
do { \
preempt_count_inc(); \
barrier(); \
} while (0)
原来在preempt_disable 中调用preempt_count_inc来让#define preempt_count_inc() preempt_count_add(1) preempt加一,这样再通过in_atomic_preempt_off()判断preempt是否为0肯定就是就是不成立的。因此kernel就会打印BUG: scheduling while atomic
static int handle_en_event(struct hns_roce_dev *hr_dev, u8 port, unsigned long event){ struct device *dev = &hr_dev->pdev->dev; struct net_device *netde
linux内核打印"
BUG
:
scheduling
while
atomic
"和"bad:
scheduling
from the idle thread"错误的时候,
通常是在中断处理函数中调用了可以休眠的函数,如semaphore,mutex,sleep之类的可休眠的函数,
而linux内核要求在中断处理的时候,不允许系统调度,不允许抢占,要等到中断处理完成才能做其他事情。
因此,要充分...
遇到一个
BUG
:
scheduling
while
atomic
: kworker/0:2/370/0x00000002;看了这篇文章
BUG
:
scheduling
while
atomic
分析,是因为在原子操作上下文或者中断上下文进行了调度引起的。
先看下为什么会打印出这句:
schedule() -> __schedule() -> schedule_de
bug
()
[26578.636839] C1 [ swapper/1]
BUG
:
scheduling
while
atomic
: swapper/1/0/0x00000002
[26578.636869] C0 [ kworker/u:1] CPU1 is up
[26578.636900] C1 [ swapper/1] Modu
永远不会被预订。
Calendly与您的日历配合使用以自动安排约会。
注册免费的Calendly帐户,然后使用Calendly for Chrome扩展程序:-直接在Chrome浏览器中访问所有事件类型-选择并共享您的可用时间,只需单击几下即可满足-将事件类型标记和保存为您的收藏夹,以便更快地访问-选择特定的时间段以显示在电子邮件中以快速设置临时会议-为事件类型添加注释,只有您和您的团队可以看到。使用我们的Chrome扩展程序,您还可以直接从Gmail访问Calendly可以:-快速建立临时会议-共享指向Calendly事件计划页面的链接关于CALENDLY日历与您的个人和企业日历联系在一起,以节省您的时间并简化与公司外部人员会面的任务。
现在,您可以在最佳时间联系并同意您的被邀请者,以开会和安排会议的时间,而无需来回电子邮件。
执行npm i -g sequelize-cli
检查config/config.json到配置数据库。 如果需要更改用户名和密码
执行sequelize db:create创建数据库
执行sequelize db:migrate创建表
执行这个命令: npm start
打开浏览器并转到http://localhost:4000
import time
stamp = datetime . datetime . now (). strftime ( "%H:%M:%S" )
time . sleep ( 5 )
print ( f"Foo - { stamp } + 5 seconds" )
计划foo.py每十分钟执行一次:
hickory schedule foo.py --every=10minutes
检查所有排队时间表的状态:
hickory status
停止并删除foo.py的计划:
hickory kill foo.py
macOS-日志与计划
语言:English
x.ai是一个免费的工具,可以共享理想的可用性和计划会议。
将x.ai的调度工具的强大功能转换为浏览器。从任何地方访问您的可用性,并快速轻松地与您的会议客人分享。单击浏览器中的扩展名图以随时随地在任何地方开始新会议。快速复制任何地方的可用性和粘贴按钮。您的客人点击适用于他们的时间,会议立即定于会议!只需单击“复制您的日历页面URL即可轻松分享它们。查看即将到来的会议并进行更改。您甚至可以将您可用的会议时间块复制到剪贴板上并在任何地方粘贴它们!访问您的日历页面并使用X.AI快速访问按钮直接在Gmail中使用会议模板。即使他们不在您的组织中,快速请求与快速访问按钮中的任何人会面。尚未尝试从X.AI中尝试强大的调度工具,每次都会安排每次会议?免费!注册这里:https://x.ai
语言:English
教练功能齐全的调度程序:免费的日历替代
借助自动计划程序来回消除:1.设置一周中的工作时间2.连接日历以自动检查繁忙时间并添加计划的事件只要共享您的个人计划链接,人们就会立即选择时间进行保存您和您的客户的时间。
你们其中之一需要重新安排时间或取消吗?
就像单击链接并选择新时间一样简单。
提供可选原因,并且将通知另一方有关更改的信息。
每月节省几个小时。
免费和功能齐全的Calendly替代方案。