参加する代わりに
実際、64ビットレジスタの操作画面では、いくつかの問題が隠されています。
まず 、64ビットレジスタを使用する機器のメンテナンスは、64ビットコアと32ビットコアの両方で利用できる必要があります。
第二に 、すべての64ビットレジスタが1つのコマンドで記述できるわけではありません。これは、ハードウェアでの実装の微妙な違いによるものです。
第三に 、確立された標準とプロトコルに関連して、64ビットの数値を2つの32ビットの数値と比較する必要がある場合があります。
自転車の発明を回避し、コードをより簡潔に、より簡潔に、より美しくする方法を見てみましょう。
64ビットデータ交換
もちろん、多くの人が
writel()
、
readl()
など、機器のレジスタを読み書きするためのよく知られたコマンドに
readl()
。
これらは、従来のバイト、ダブルバイト、および4バイトのレジスタ操作をカバーしています。 一度に8バイトを読み書きする必要がある場合はどうしますか?
一部の64ビットアーキテクチャでは、
writeq()
および
readq()
コマンドが
readq()
ます。
従来、32ビットプラットフォームと64ビットプラットフォームを採用するプログラマーは、コードで似たようなものを作成していました。
static inline void writeq(u64 val, void __iomem *addr) { writel(val, addr); writel(val >> 32, addr + 4); }
そしてそれに応じて読書。
static inline u64 readq(void __iomem *addr) { u32 low, high; low = readl(addr); high = readl(addr + 4); return low + ((u64)high << 32); }
そして、そのようなコピーが数百ではないとしても数十あると想像してください。 自転車の発明を避けるために、特別なファイルには/ linux / io-64-nonatomic-hi-lo.hが 含まれ、/ linux / io-64-nonatomic-lo-hi.hがカーネルに追加されました 。
これらのファイルの機能は何ですか:
- 特定の関数は、アトミックにではなく呼び出しを実行します。
- 上記に関連して、カーネルには2つのファイルがあります。ジュニア-シニアとその逆-シニア-ジュニアを記録するためです。
- どちらのファイルも、「最初に起きた人はスニーカーだ」という原則に従って、
writeq()
とreadq()
宣言します。 最初に、それらがすでに定義されているかどうかがチェックされますか? そうでない場合は、再定義します。 したがって、ヘッダーファイルが含まれる順序が重要です。 - 式8 = 4 + 4によって明らかに行われる処理。
したがって、4 + 4という形式の呼び出しのみを理解する機器がある場合は、
lo_hi_writeq()
および
lo_hi_readq()
または
hi_lo_writeq()
および
hi_lo_readq()
ます。 理想的なケースでは、
writeq()
および
readq()
です。
64ビット数の比較
場合によっては、オプション8の64ビット数とオプション4 + 4の数を比較する必要があります。
額に直接ソリューション:
u32 hi = Y, lo = Z; u64 value = X, tmp; tmp = (Y << 32) | X; return value == tmp;
さて、あなたは32ビットアーキテクチャ上にどれだけのコードがあるのか理解しています。
このケースは、次の2つの比較に分けることができます。
return (value >> 32) == hi && (u32)value == lo;
簡単に思えますが、1つ問題があります。 カーネルには、特定のプラットフォームに直接依存するタイプ、つまりphys_addr_t 、 resource_size_t 、 dma_addr_tなどがあります。
このコードを書いたらどうなると思いますか:
u32 hi = Y, lo = Z; resource_size_t value = X; return (value >> 32) == hi && (u32)value == lo;
もちろん、64ビットアーキテクチャでは、すべて問題ありません。 しかし、32ビット版では、コンパイラーはシフト
value >> 32
について文句を言います。
コンパイラが満足し、ユーザーが
lower_32_bits()
ないようにするために、次のマクロがカーネルに追加されました:
lower_32_bits()
および
upper_32_bits()
、それぞれ下位および上位4バイト。
その結果、比較は次のようになります。
return upper_32_bits(value) == hi && lower_32_bits(value) == lo;
これらの操作はアトミックではないことを忘れないでください!